bug-buddy r2751 - in trunk: . gnome-breakpad google-breakpad google-breakpad/src/client google-breakpad/src/client/linux/handler google-breakpad/src/client/mac/handler google-breakpad/src/client/mac/handler/minidump_test.xcodeproj google-breakpad/src/client/solaris/handler google-breakpad/src/client/windows google-breakpad/src/client/windows/common google-breakpad/src/client/windows/crash_generation google-breakpad/src/client/windows/handler google-breakpad/src/client/windows/sender google-breakpad/src/common google-breakpad/src/common/linux google-breakpad/src/common/mac google-breakpad/src/common/mac/dwarf google-breakpad/src/common/solaris google-breakpad/src/common/windows google-breakpad/src/google_breakpad/common google-breakpad/src/google_breakpad/processor google-breakpad/src/processor google-breakpad/src/tools/linux/dump_syms google-breakpad/src/tools/linux/symupload google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj google-breakpad/src/tools/ mac/dump_syms google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj google-breakpad/src/tools/mac/symupload google-breakpad/src/tools/solaris google-breakpad/src/tools/solaris/dump_syms google-breakpad/src/tools/windows/converter google-breakpad/src/tools/windows/dump_syms google-breakpad/src/tools/windows/symupload
- From: cosimoc svn gnome org
- To: svn-commits-list gnome org
- Subject: bug-buddy r2751 - in trunk: . gnome-breakpad google-breakpad google-breakpad/src/client google-breakpad/src/client/linux/handler google-breakpad/src/client/mac/handler google-breakpad/src/client/mac/handler/minidump_test.xcodeproj google-breakpad/src/client/solaris/handler google-breakpad/src/client/windows google-breakpad/src/client/windows/common google-breakpad/src/client/windows/crash_generation google-breakpad/src/client/windows/handler google-breakpad/src/client/windows/sender google-breakpad/src/common google-breakpad/src/common/linux google-breakpad/src/common/mac google-breakpad/src/common/mac/dwarf google-breakpad/src/common/solaris google-breakpad/src/common/windows google-breakpad/src/google_breakpad/common google-breakpad/src/google_breakpad/processor google-breakpad/src/processor google-breakpad/src/tools/linux/dump_syms google-breakpad/src/tools/linux/symupload google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj google-breakpad/src/tools/ mac/dump_syms google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj google-breakpad/src/tools/mac/symupload google-breakpad/src/tools/solaris google-breakpad/src/tools/solaris/dump_syms google-breakpad/src/tools/windows/converter google-breakpad/src/tools/windows/dump_syms google-breakpad/src/tools/windows/symupload
- Date: Sun, 19 Oct 2008 13:26:38 +0000 (UTC)
Author: cosimoc
Date: Sun Oct 19 13:26:38 2008
New Revision: 2751
URL: http://svn.gnome.org/viewvc/bug-buddy?rev=2751&view=rev
Log:
2008-10-19 Cosimo Cecchi <cosimoc gnome org>
* */*: Update google-breakpad to r290.
Added:
trunk/google-breakpad/src/client/mac/handler/breakpad_exc_server.c
trunk/google-breakpad/src/client/mac/handler/breakpad_exc_server.h
trunk/google-breakpad/src/client/mac/handler/breakpad_nlist_64.cc
trunk/google-breakpad/src/client/mac/handler/breakpad_nlist_64.h
trunk/google-breakpad/src/client/windows/common/
trunk/google-breakpad/src/client/windows/common/auto_critical_section.h
trunk/google-breakpad/src/client/windows/common/ipc_protocol.h
trunk/google-breakpad/src/client/windows/crash_generation/
trunk/google-breakpad/src/client/windows/crash_generation/ReadMe.txt
trunk/google-breakpad/src/client/windows/crash_generation/client_info.cc
trunk/google-breakpad/src/client/windows/crash_generation/client_info.h
trunk/google-breakpad/src/client/windows/crash_generation/crash_generation.vcproj
trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc
trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h
trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc
trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h
trunk/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc
trunk/google-breakpad/src/client/windows/crash_generation/minidump_generator.h
trunk/google-breakpad/src/common/mac/dwarf/
trunk/google-breakpad/src/common/mac/dwarf/bytereader-inl.h
trunk/google-breakpad/src/common/mac/dwarf/bytereader.cc
trunk/google-breakpad/src/common/mac/dwarf/bytereader.h
trunk/google-breakpad/src/common/mac/dwarf/dwarf2enums.h
trunk/google-breakpad/src/common/mac/dwarf/dwarf2reader.cc
trunk/google-breakpad/src/common/mac/dwarf/dwarf2reader.h
trunk/google-breakpad/src/common/mac/dwarf/functioninfo.cc
trunk/google-breakpad/src/common/mac/dwarf/functioninfo.h
trunk/google-breakpad/src/common/mac/dwarf/line_state_machine.h
trunk/google-breakpad/src/common/mac/dwarf/types.h
trunk/google-breakpad/src/common/md5.c
trunk/google-breakpad/src/common/md5.h
trunk/google-breakpad/src/common/solaris/dump_symbols.cc
trunk/google-breakpad/src/common/solaris/dump_symbols.h
trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h
trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h
trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h
trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h
trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h
trunk/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h
trunk/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h
trunk/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h
trunk/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h
trunk/google-breakpad/src/processor/stackwalker_amd64.cc
trunk/google-breakpad/src/processor/stackwalker_amd64.h
trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.mm
trunk/google-breakpad/src/tools/solaris/
trunk/google-breakpad/src/tools/solaris/dump_syms/
trunk/google-breakpad/src/tools/solaris/dump_syms/Makefile
trunk/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc
Removed:
trunk/google-breakpad/src/common/linux/md5.c
trunk/google-breakpad/src/common/linux/md5.h
Modified:
trunk/ChangeLog
trunk/gnome-breakpad/Makefile.am
trunk/google-breakpad/ChangeLog
trunk/google-breakpad/Makefile.am
trunk/google-breakpad/src/client/linux/handler/Makefile
trunk/google-breakpad/src/client/linux/handler/exception_handler.cc
trunk/google-breakpad/src/client/linux/handler/exception_handler.h
trunk/google-breakpad/src/client/linux/handler/linux_thread.cc
trunk/google-breakpad/src/client/linux/handler/minidump_generator.cc
trunk/google-breakpad/src/client/mac/handler/dynamic_images.cc
trunk/google-breakpad/src/client/mac/handler/dynamic_images.h
trunk/google-breakpad/src/client/mac/handler/exception_handler.cc
trunk/google-breakpad/src/client/mac/handler/minidump_generator.cc
trunk/google-breakpad/src/client/mac/handler/minidump_generator.h
trunk/google-breakpad/src/client/mac/handler/minidump_generator_test.cc
trunk/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj
trunk/google-breakpad/src/client/minidump_file_writer_unittest.cc
trunk/google-breakpad/src/client/solaris/handler/Makefile
trunk/google-breakpad/src/client/solaris/handler/exception_handler.cc
trunk/google-breakpad/src/client/solaris/handler/exception_handler.h
trunk/google-breakpad/src/client/solaris/handler/minidump_generator.cc
trunk/google-breakpad/src/client/solaris/handler/minidump_generator.h
trunk/google-breakpad/src/client/solaris/handler/minidump_test.cc
trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.cc
trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.h
trunk/google-breakpad/src/client/windows/breakpad_client.sln
trunk/google-breakpad/src/client/windows/handler/exception_handler.cc
trunk/google-breakpad/src/client/windows/handler/exception_handler.h
trunk/google-breakpad/src/client/windows/handler/exception_handler.vcproj
trunk/google-breakpad/src/client/windows/sender/crash_report_sender.cc
trunk/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj
trunk/google-breakpad/src/common/linux/dump_symbols.cc
trunk/google-breakpad/src/common/linux/file_id.cc
trunk/google-breakpad/src/common/linux/http_upload.cc
trunk/google-breakpad/src/common/linux/http_upload.h
trunk/google-breakpad/src/common/mac/dump_syms.h
trunk/google-breakpad/src/common/mac/dump_syms.mm
trunk/google-breakpad/src/common/solaris/file_id.cc
trunk/google-breakpad/src/common/string_conversion.cc
trunk/google-breakpad/src/common/windows/http_upload.cc
trunk/google-breakpad/src/common/windows/string_utils-inl.h
trunk/google-breakpad/src/google_breakpad/common/breakpad_types.h
trunk/google-breakpad/src/google_breakpad/common/minidump_format.h
trunk/google-breakpad/src/google_breakpad/processor/minidump.h
trunk/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h
trunk/google-breakpad/src/processor/logging.cc
trunk/google-breakpad/src/processor/minidump.cc
trunk/google-breakpad/src/processor/minidump_processor.cc
trunk/google-breakpad/src/processor/minidump_stackwalk.cc
trunk/google-breakpad/src/processor/simple_symbol_supplier.cc
trunk/google-breakpad/src/processor/stackwalker.cc
trunk/google-breakpad/src/processor/stackwalker_selftest.cc
trunk/google-breakpad/src/tools/linux/dump_syms/Makefile
trunk/google-breakpad/src/tools/linux/symupload/Makefile
trunk/google-breakpad/src/tools/linux/symupload/minidump_upload.cc
trunk/google-breakpad/src/tools/linux/symupload/sym_upload.cc
trunk/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
trunk/google-breakpad/src/tools/mac/symupload/symupload.m
trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
trunk/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
trunk/google-breakpad/src/tools/windows/symupload/symupload.vcproj
Modified: trunk/gnome-breakpad/Makefile.am
==============================================================================
--- trunk/gnome-breakpad/Makefile.am (original)
+++ trunk/gnome-breakpad/Makefile.am Sun Oct 19 13:26:38 2008
@@ -12,8 +12,7 @@
if BREAKPAD_LINUX
dir = linux
GOOGLE_BREAKPAD_CC_EXTRA = \
- $(top_srcdir)/google-breakpad/src/client/linux/handler/linux_thread.cc \
- $(top_srcdir)/google-breakpad/src/common/linux/md5.c
+ $(top_srcdir)/google-breakpad/src/client/linux/handler/linux_thread.cc
endif
@@ -25,6 +24,7 @@
$(top_srcdir)/google-breakpad/src/client/minidump_file_writer.cc \
$(top_srcdir)/google-breakpad/src/common/string_conversion.cc \
$(top_srcdir)/google-breakpad/src/common/convert_UTF.c \
+ $(top_srcdir)/google-breakpad/src/common/md5.c \
$(GOOGLE_BREAKPAD_CC_EXTRA)
GOOGLE_BREAKPAD_LIBS = $(top_builddir)/google-breakpad/src/libbreakpad.la -lpthread
Modified: trunk/google-breakpad/Makefile.am
==============================================================================
--- trunk/google-breakpad/Makefile.am (original)
+++ trunk/google-breakpad/Makefile.am Sun Oct 19 13:26:38 2008
@@ -87,16 +87,18 @@
src/processor/minidump_processor.cc \
src/processor/pathname_stripper.cc \
src/processor/pathname_stripper.h \
- src/processor/postfix_evaluator.h \
src/processor/postfix_evaluator-inl.h \
+ src/processor/postfix_evaluator.h \
src/processor/process_state.cc \
- src/processor/range_map.h \
src/processor/range_map-inl.h \
+ src/processor/range_map.h \
src/processor/scoped_ptr.h \
src/processor/simple_symbol_supplier.cc \
src/processor/simple_symbol_supplier.h \
src/processor/stack_frame_info.h \
src/processor/stackwalker.cc \
+ src/processor/stackwalker_amd64.cc \
+ src/processor/stackwalker_amd64.h \
src/processor/stackwalker_ppc.cc \
src/processor/stackwalker_ppc.h \
src/processor/stackwalker_sparc.cc \
@@ -165,6 +167,7 @@
src/processor/pathname_stripper.lo \
src/processor/process_state.lo \
src/processor/stackwalker.lo \
+ src/processor/stackwalker_amd64.lo \
src/processor/stackwalker_ppc.lo \
src/processor/stackwalker_sparc.lo \
src/processor/stackwalker_x86.lo
@@ -196,6 +199,7 @@
src/processor/minidump.lo \
src/processor/pathname_stripper.lo \
src/processor/stackwalker.lo \
+ src/processor/stackwalker_amd64.lo \
src/processor/stackwalker_ppc.lo \
src/processor/stackwalker_sparc.lo \
src/processor/stackwalker_x86.lo
@@ -225,6 +229,7 @@
src/processor/process_state.lo \
src/processor/simple_symbol_supplier.lo \
src/processor/stackwalker.lo \
+ src/processor/stackwalker_amd64.lo \
src/processor/stackwalker_ppc.lo \
src/processor/stackwalker_sparc.lo \
src/processor/stackwalker_x86.lo
@@ -292,8 +297,6 @@
src/common/linux/guid_creator.h \
src/common/linux/http_upload.cc \
src/common/linux/http_upload.h \
- src/common/linux/md5.c \
- src/common/linux/md5.h \
src/common/mac/HTTPMultipartUpload.h \
src/common/mac/HTTPMultipartUpload.m \
src/common/mac/dump_syms.h \
@@ -308,6 +311,10 @@
src/common/mac/macho_walker.h \
src/common/mac/string_utilities.cc \
src/common/mac/string_utilities.h \
+ src/common/md5.c \
+ src/common/md5.h \
+ src/common/solaris/dump_symbols.cc \
+ src/common/solaris/dump_symbols.h \
src/common/solaris/file_id.cc \
src/common/solaris/file_id.h \
src/common/solaris/guid_creator.cc \
@@ -343,6 +350,13 @@
src/tools/mac/symupload/minidump_upload.m \
src/tools/mac/symupload/symupload.m \
src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj \
+ src/tools/solaris/dump_syms/Makefile \
+ src/tools/solaris/dump_syms/dump_syms.cc \
+ src/tools/solaris/dump_syms/run_regtest.sh \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
src/tools/windows/converter/ms_symbol_server_converter.cc \
src/tools/windows/converter/ms_symbol_server_converter.h \
src/tools/windows/converter/ms_symbol_server_converter.vcproj \
Modified: trunk/google-breakpad/src/client/linux/handler/Makefile
==============================================================================
--- trunk/google-breakpad/src/client/linux/handler/Makefile (original)
+++ trunk/google-breakpad/src/client/linux/handler/Makefile Sun Oct 19 13:26:38 2008
@@ -29,7 +29,7 @@
MINIDUMP_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(MINIDUMP_TEST_SRC))\
$(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ)
EXCEPTION_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(EXCEPTION_TEST_SRC))\
- $(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ) $(HANDLER_SRC)
+ $(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ) $(HANDLER_OBJ)
BIN=$(BIN_DIR)/minidump_test\
$(BIN_DIR)/linux_thread_test\
@@ -48,7 +48,7 @@
$(BIN_DIR)/exception_handler_test:$(EXCEPTION_TEST_OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@
-md5.o:../../../common/linux/md5.c
+md5.o:../../../common/md5.c
$(CC) $(CXXFLAGS) -c $^
clean:
Modified: trunk/google-breakpad/src/client/linux/handler/exception_handler.cc
==============================================================================
--- trunk/google-breakpad/src/client/linux/handler/exception_handler.cc (original)
+++ trunk/google-breakpad/src/client/linux/handler/exception_handler.cc Sun Oct 19 13:26:38 2008
@@ -42,6 +42,7 @@
#include <cassert>
#include <cstdlib>
#include <ctime>
+#include <linux/limits.h>
#include "client/linux/handler/exception_handler.h"
#include "common/linux/guid_creator.h"
@@ -122,7 +123,9 @@
}
bool ExceptionHandler::WriteMinidump() {
- return InternalWriteMinidump(0, 0, NULL);
+ bool success = InternalWriteMinidump(0, 0, NULL);
+ UpdateNextID();
+ return success;
}
// static
@@ -232,41 +235,49 @@
if (filter_ && !filter_(callback_context_))
return false;
+ bool success = false;
+ // Block all the signals we want to process when writting minidump.
+ // We don't want it to be interrupted.
+ sigset_t sig_blocked, sig_old;
+ bool blocked = true;
+ sigfillset(&sig_blocked);
+ for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i)
+ sigdelset(&sig_blocked, SigTable[i]);
+ if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) {
+ blocked = false;
+ fprintf(stderr, "google_breakpad::ExceptionHandler::HandleException: "
+ "failed to block signals.\n");
+ }
+
+ success = minidump_generator_.WriteMinidumpToFile(
+ next_minidump_path_c_, signo, sighandler_ebp, sig_ctx);
+
+ // Unblock the signals.
+ if (blocked) {
+ sigprocmask(SIG_SETMASK, &sig_old, &sig_old);
+ }
+
+ if (callback_)
+ success = callback_(dump_path_c_, next_minidump_id_c_,
+ callback_context_, success);
+ return success;
+}
+
+void ExceptionHandler::UpdateNextID() {
GUID guid;
- bool success = false;;
char guid_str[kGUIDStringLength + 1];
if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) {
+ next_minidump_id_ = guid_str;
+ next_minidump_id_c_ = next_minidump_id_.c_str();
+
char minidump_path[PATH_MAX];
snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp",
dump_path_c_,
guid_str);
- // Block all the signals we want to process when writting minidump.
- // We don't want it to be interrupted.
- sigset_t sig_blocked, sig_old;
- bool blocked = true;
- sigfillset(&sig_blocked);
- for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i)
- sigdelset(&sig_blocked, SigTable[i]);
- if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) {
- blocked = false;
- fprintf(stderr, "google_breakpad::ExceptionHandler::HandleException: "
- "failed to block signals.\n");
- }
-
- success = minidump_generator_.WriteMinidumpToFile(
- minidump_path, signo, sighandler_ebp, sig_ctx);
-
- // Unblock the signals.
- if (blocked) {
- sigprocmask(SIG_SETMASK, &sig_old, &sig_old);
- }
-
- if (callback_)
- success = callback_(dump_path_c_, guid_str,
- callback_context_, success);
+ next_minidump_path_ = minidump_path;
+ next_minidump_path_c_ = next_minidump_path_.c_str();
}
- return success;
}
} // namespace google_breakpad
Modified: trunk/google-breakpad/src/client/linux/handler/exception_handler.h
==============================================================================
--- trunk/google-breakpad/src/client/linux/handler/exception_handler.h (original)
+++ trunk/google-breakpad/src/client/linux/handler/exception_handler.h Sun Oct 19 13:26:38 2008
@@ -126,6 +126,7 @@
void set_dump_path(const string &dump_path) {
dump_path_ = dump_path;
dump_path_c_ = dump_path_.c_str();
+ UpdateNextID();
}
// Writes a minidump immediately. This can be used to capture the
@@ -160,6 +161,10 @@
bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp,
struct sigcontext **sig_ctx);
+ // Generates a new ID and stores it in next_minidump_id, and stores the
+ // path of the next minidump to be written in next_minidump_path_.
+ void UpdateNextID();
+
private:
FilterCallback filter_;
MinidumpCallback callback_;
@@ -168,9 +173,20 @@
// 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.
+
+ // The basename of the next minidump to be written, without the extension
+ string next_minidump_id_;
+
+ // The full pathname of the next minidump to be written, including the file
+ // extension
+ string next_minidump_path_;
+
+ // Pointers to C-string representations of the above. These are set
+ // when the above are set so we can avoid calling c_str during
+ // an exception.
const char *dump_path_c_;
+ const char *next_minidump_id_c_;
+ const char *next_minidump_path_c_;
// True if the ExceptionHandler installed an unhandled exception filter
// when created (with an install_handler parameter set to true).
Modified: trunk/google-breakpad/src/client/linux/handler/linux_thread.cc
==============================================================================
--- trunk/google-breakpad/src/client/linux/handler/linux_thread.cc (original)
+++ trunk/google-breakpad/src/client/linux/handler/linux_thread.cc Sun Oct 19 13:26:38 2008
@@ -44,7 +44,6 @@
#include <cassert>
#include <cstdio>
#include <cstdlib>
-#include <cstring>
#include <functional>
#include "client/linux/handler/linux_thread.h"
Modified: trunk/google-breakpad/src/client/linux/handler/minidump_generator.cc
==============================================================================
--- trunk/google-breakpad/src/client/linux/handler/minidump_generator.cc (original)
+++ trunk/google-breakpad/src/client/linux/handler/minidump_generator.cc Sun Oct 19 13:26:38 2008
@@ -42,6 +42,7 @@
#include <cstdlib>
#include <cstring>
#include <ctime>
+#include <string.h>
#include "common/linux/file_id.h"
#include "client/linux/handler/linux_thread.h"
Added: trunk/google-breakpad/src/client/mac/handler/breakpad_exc_server.c
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/mac/handler/breakpad_exc_server.c Sun Oct 19 13:26:38 2008
@@ -0,0 +1,1750 @@
+/*
+ * IDENTIFICATION:
+ * stub generated Mon Jun 16 18:08:10 2008
+ * with a MiG generated Tue Feb 19 02:01:43 PST 2008 by root b75 local
+ * OPTIONS:
+ */
+
+/* Module exc */
+
+#define __MIG_check__Request__exc_subsystem__ 1
+#define __NDR_convert__Request__exc_subsystem__ 1
+
+#include <string.h>
+#include <mach/ndr.h>
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/notify.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+#include <mach/port.h>
+
+#include <mach/std_types.h>
+#include <mach/mig.h>
+#include <mach/mig.h>
+#include <mach/mach_types.h>
+
+#ifndef mig_internal
+#define mig_internal static __inline__
+#endif /* mig_internal */
+
+#ifndef mig_external
+#define mig_external
+#endif /* mig_external */
+
+#if !defined(__MigTypeCheck) && defined(TypeCheck)
+#define __MigTypeCheck TypeCheck /* Legacy setting */
+#endif /* !defined(__MigTypeCheck) */
+
+#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
+#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
+#endif /* !defined(__MigKernelSpecificCode) */
+
+#ifndef LimitCheck
+#define LimitCheck 0
+#endif /* LimitCheck */
+
+#ifndef min
+#define min(a,b) ( ((a) < (b))? (a): (b) )
+#endif /* min */
+
+#if !defined(_WALIGN_)
+#define _WALIGN_(x) (((x) + 3) & ~3)
+#endif /* !defined(_WALIGN_) */
+
+#if !defined(_WALIGNSZ_)
+#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
+#endif /* !defined(_WALIGNSZ_) */
+
+#ifndef UseStaticTemplates
+#define UseStaticTemplates 0
+#endif /* UseStaticTemplates */
+
+#ifndef __DeclareRcvRpc
+#define __DeclareRcvRpc(_NUM_, _NAME_)
+#endif /* __DeclareRcvRpc */
+
+#ifndef __BeforeRcvRpc
+#define __BeforeRcvRpc(_NUM_, _NAME_)
+#endif /* __BeforeRcvRpc */
+
+#ifndef __AfterRcvRpc
+#define __AfterRcvRpc(_NUM_, _NAME_)
+#endif /* __AfterRcvRpc */
+
+#ifndef __DeclareRcvSimple
+#define __DeclareRcvSimple(_NUM_, _NAME_)
+#endif /* __DeclareRcvSimple */
+
+#ifndef __BeforeRcvSimple
+#define __BeforeRcvSimple(_NUM_, _NAME_)
+#endif /* __BeforeRcvSimple */
+
+#ifndef __AfterRcvSimple
+#define __AfterRcvSimple(_NUM_, _NAME_)
+#endif /* __AfterRcvSimple */
+
+#define novalue void
+
+#define msgh_request_port msgh_local_port
+#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
+#define msgh_reply_port msgh_remote_port
+#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
+
+#define MIG_RETURN_ERROR(X, code) {\
+ ((mig_reply_error_t *)X)->RetCode = code;\
+ ((mig_reply_error_t *)X)->NDR = NDR_record;\
+ return;\
+ }
+
+/* typedefs for all requests */
+
+#ifndef __Request__exc_subsystem__defined
+#define __Request__exc_subsystem__defined
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ } __Request__exception_raise_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ int flavor;
+ mach_msg_type_number_t old_stateCnt;
+ natural_t old_state[144];
+ } __Request__exception_raise_state_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ int flavor;
+ mach_msg_type_number_t old_stateCnt;
+ natural_t old_state[144];
+ } __Request__exception_raise_state_identity_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+#endif /* !__Request__exc_subsystem__defined */
+
+/* typedefs for all replies */
+
+#ifndef __Reply__exc_subsystem__defined
+#define __Reply__exc_subsystem__defined
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ } __Reply__exception_raise_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ int flavor;
+ mach_msg_type_number_t new_stateCnt;
+ natural_t new_state[144];
+ } __Reply__exception_raise_state_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ int flavor;
+ mach_msg_type_number_t new_stateCnt;
+ natural_t new_state[144];
+ } __Reply__exception_raise_state_identity_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+#endif /* !__Reply__exc_subsystem__defined */
+
+
+/* union of all replies */
+
+#ifndef __ReplyUnion__breakpad_exc_subsystem__defined
+#define __ReplyUnion__breakpad_exc_subsystem__defined
+union __ReplyUnion__breakpad_exc_subsystem {
+ __Reply__exception_raise_t Reply_exception_raise;
+ __Reply__exception_raise_state_t Reply_exception_raise_state;
+ __Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
+};
+#endif /* __RequestUnion__breakpad_exc_subsystem__defined */
+/* Forward Declarations */
+
+
+mig_internal novalue _Xexception_raise
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
+
+mig_internal novalue _Xexception_raise_state
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
+
+mig_internal novalue _Xexception_raise_state_identity
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
+
+
+#if ( __MigTypeCheck || __NDR_convert__ )
+#if __MIG_check__Request__exc_subsystem__
+#if !defined(__MIG_check__Request__exception_raise_t__defined)
+#define __MIG_check__Request__exception_raise_t__defined
+#ifndef __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#if defined(__NDR_convert__int_rep__exc__exception_type_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__exception_type_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__int_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__int_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_t__exception__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#if defined(__NDR_convert__int_rep__exc__exception_data_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__int_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exception_data_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__int_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exc__integer_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__exc__integer_t)
+#elif defined(__NDR_convert__int_rep__integer_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__integer_t)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__exc__int32_t)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_t__code__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined
+#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt(a, f) \
+ __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt(a, f) \
+ __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#if defined(__NDR_convert__char_rep__exc__exception_type_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__exception_type_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__char_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__char_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_t__exception__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#if defined(__NDR_convert__char_rep__exc__exception_data_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__char_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exception_data_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__char_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exc__integer_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__exc__integer_t)
+#elif defined(__NDR_convert__char_rep__integer_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__integer_t)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__exc__int32_t)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_t__code__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#if defined(__NDR_convert__float_rep__exc__exception_type_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__exception_type_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__float_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \
+ __NDR_convert__float_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_t__exception__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#if defined(__NDR_convert__float_rep__exc__exception_data_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__float_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exception_data_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__float_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exc__integer_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__exc__integer_t)
+#elif defined(__NDR_convert__float_rep__integer_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__integer_t)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__exc__int32_t)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_t__code__defined */
+
+
+mig_internal kern_return_t __MIG_check__Request__exception_raise_t(__attribute__((__unused__)) __Request__exception_raise_t *In0P)
+{
+
+ typedef __Request__exception_raise_t __Request;
+#if __MigTypeCheck
+ unsigned int msgh_size;
+#endif /* __MigTypeCheck */
+
+#if __MigTypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
+ (In0P->msgh_body.msgh_descriptor_count != 2) ||
+ (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 8)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))
+)
+ return MIG_BAD_ARGUMENTS;
+#endif /* __MigTypeCheck */
+
+#if __MigTypeCheck
+ if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
+ In0P->thread.disposition != 17)
+ return MIG_TYPE_ERROR;
+#endif /* __MigTypeCheck */
+
+#if __MigTypeCheck
+ if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
+ In0P->task.disposition != 17)
+ return MIG_TYPE_ERROR;
+#endif /* __MigTypeCheck */
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep)
+ __NDR_convert__int_rep__Request__exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined */
+#if __MigTypeCheck
+ if (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 8) + ((4 * In0P->codeCnt)))
+ return MIG_BAD_ARGUMENTS;
+#endif /* __MigTypeCheck */
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_t__exception__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_t__code__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep) {
+#if defined(__NDR_convert__int_rep__Request__exception_raise_t__exception__defined)
+ __NDR_convert__int_rep__Request__exception_raise_t__exception(&In0P->exception, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_t__exception__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_t__code__defined)
+ __NDR_convert__int_rep__Request__exception_raise_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_t__code__defined */
+ }
+#endif /* defined(__NDR_convert__int_rep...) */
+
+#if defined(__NDR_convert__char_rep__Request__exception_raise_t__exception__defined) || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_t__code__defined) || \
+ 0
+ if (In0P->NDR.char_rep != NDR_record.char_rep) {
+#if defined(__NDR_convert__char_rep__Request__exception_raise_t__exception__defined)
+ __NDR_convert__char_rep__Request__exception_raise_t__exception(&In0P->exception, In0P->NDR.char_rep);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_t__exception__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_t__code__defined)
+ __NDR_convert__char_rep__Request__exception_raise_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_t__code__defined */
+ }
+#endif /* defined(__NDR_convert__char_rep...) */
+
+#if defined(__NDR_convert__float_rep__Request__exception_raise_t__exception__defined) || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_t__code__defined) || \
+ 0
+ if (In0P->NDR.float_rep != NDR_record.float_rep) {
+#if defined(__NDR_convert__float_rep__Request__exception_raise_t__exception__defined)
+ __NDR_convert__float_rep__Request__exception_raise_t__exception(&In0P->exception, In0P->NDR.float_rep);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_t__exception__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_t__code__defined)
+ __NDR_convert__float_rep__Request__exception_raise_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_t__code__defined */
+ }
+#endif /* defined(__NDR_convert__float_rep...) */
+
+ return MACH_MSG_SUCCESS;
+}
+#endif /* !defined(__MIG_check__Request__exception_raise_t__defined) */
+#endif /* __MIG_check__Request__exc_subsystem__ */
+#endif /* ( __MigTypeCheck || __NDR_convert__ ) */
+
+
+/* Routine exception_raise */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif /* mig_external */
+kern_return_t breakpad_exception_raise
+(
+ mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt
+);
+
+/* Routine exception_raise */
+mig_internal novalue _Xexception_raise
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ mach_msg_trailer_t trailer;
+ } Request;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+ typedef __Request__exception_raise_t __Request;
+ typedef __Reply__exception_raise_t Reply;
+
+ /*
+ * typedef struct {
+ * mach_msg_header_t Head;
+ * NDR_record_t NDR;
+ * kern_return_t RetCode;
+ * } mig_reply_error_t;
+ */
+
+ Request *In0P = (Request *) InHeadP;
+ Reply *OutP = (Reply *) OutHeadP;
+#ifdef __MIG_check__Request__exception_raise_t__defined
+ kern_return_t check_result;
+#endif /* __MIG_check__Request__exception_raise_t__defined */
+
+ __DeclareRcvRpc(2401, "exception_raise")
+ __BeforeRcvRpc(2401, "exception_raise")
+
+#if defined(__MIG_check__Request__exception_raise_t__defined)
+ check_result = __MIG_check__Request__exception_raise_t((__Request *)In0P);
+ if (check_result != MACH_MSG_SUCCESS)
+ { MIG_RETURN_ERROR(OutP, check_result); }
+#endif /* defined(__MIG_check__Request__exception_raise_t__defined) */
+
+ OutP->RetCode = breakpad_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt);
+
+ OutP->NDR = NDR_record;
+
+
+ __AfterRcvRpc(2401, "exception_raise")
+}
+
+#if ( __MigTypeCheck || __NDR_convert__ )
+#if __MIG_check__Request__exc_subsystem__
+#if !defined(__MIG_check__Request__exception_raise_state_t__defined)
+#define __MIG_check__Request__exception_raise_state_t__defined
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#if defined(__NDR_convert__int_rep__exc__exception_type_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__exception_type_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__int_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__int_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#if defined(__NDR_convert__int_rep__exc__exception_data_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__int_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exception_data_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__int_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exc__integer_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__exc__integer_t)
+#elif defined(__NDR_convert__int_rep__integer_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__integer_t)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__exc__int32_t)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined
+#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(a, f) \
+ __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(a, f) \
+ __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined
+#if defined(__NDR_convert__int_rep__exc__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__int_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__int_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__int_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#if defined(__NDR_convert__int_rep__exc__thread_state_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__int_rep__exc__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__thread_state_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exc__natural_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__exc__natural_t)
+#elif defined(__NDR_convert__int_rep__natural_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t)
+#elif defined(__NDR_convert__int_rep__exc__uint32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__exc__uint32_t)
+#elif defined(__NDR_convert__int_rep__uint32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined
+#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(a, f) \
+ __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(a, f) \
+ __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#if defined(__NDR_convert__char_rep__exc__exception_type_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__exception_type_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__char_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__char_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#if defined(__NDR_convert__char_rep__exc__exception_data_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__char_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exception_data_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__char_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exc__integer_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__exc__integer_t)
+#elif defined(__NDR_convert__char_rep__integer_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__integer_t)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__exc__int32_t)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined
+#if defined(__NDR_convert__char_rep__exc__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__char_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__char_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__char_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#if defined(__NDR_convert__char_rep__exc__thread_state_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__char_rep__exc__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__thread_state_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exc__natural_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__exc__natural_t)
+#elif defined(__NDR_convert__char_rep__natural_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t)
+#elif defined(__NDR_convert__char_rep__exc__uint32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__exc__uint32_t)
+#elif defined(__NDR_convert__char_rep__uint32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#if defined(__NDR_convert__float_rep__exc__exception_type_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__exception_type_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__float_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \
+ __NDR_convert__float_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#if defined(__NDR_convert__float_rep__exc__exception_data_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__float_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exception_data_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__float_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exc__integer_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__exc__integer_t)
+#elif defined(__NDR_convert__float_rep__integer_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__integer_t)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__exc__int32_t)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined
+#if defined(__NDR_convert__float_rep__exc__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__float_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__float_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \
+ __NDR_convert__float_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#if defined(__NDR_convert__float_rep__exc__thread_state_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__float_rep__exc__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__thread_state_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exc__natural_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__exc__natural_t)
+#elif defined(__NDR_convert__float_rep__natural_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t)
+#elif defined(__NDR_convert__float_rep__exc__uint32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__exc__uint32_t)
+#elif defined(__NDR_convert__float_rep__uint32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined */
+
+
+mig_internal kern_return_t __MIG_check__Request__exception_raise_state_t(__attribute__((__unused__)) __Request__exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_t **In1PP)
+{
+
+ typedef __Request__exception_raise_state_t __Request;
+ __Request *In1P;
+#if __MigTypeCheck
+ unsigned int msgh_size;
+#endif /* __MigTypeCheck */
+ unsigned int msgh_size_delta;
+
+#if __MigTypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
+ (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
+ return MIG_BAD_ARGUMENTS;
+#endif /* __MigTypeCheck */
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep)
+ __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined */
+ msgh_size_delta = (4 * In0P->codeCnt);
+#if __MigTypeCheck
+ if (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584) + msgh_size_delta)
+ return MIG_BAD_ARGUMENTS;
+ msgh_size -= msgh_size_delta;
+#endif /* __MigTypeCheck */
+
+ *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8);
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep)
+ __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined */
+#if __MigTypeCheck
+ if (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 584) + ((4 * In1P->old_stateCnt)))
+ return MIG_BAD_ARGUMENTS;
+#endif /* __MigTypeCheck */
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_t__code__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep) {
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_t__exception(&In0P->exception, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__code__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.int_rep, In1P->old_stateCnt);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined */
+ }
+#endif /* defined(__NDR_convert__int_rep...) */
+
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined) || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_state_t__code__defined) || \
+ 0 || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined) || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined) || \
+ 0
+ if (In0P->NDR.char_rep != NDR_record.char_rep) {
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_t__exception(&In0P->exception, In0P->NDR.char_rep);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__code__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.char_rep);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.char_rep, In1P->old_stateCnt);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined */
+ }
+#endif /* defined(__NDR_convert__char_rep...) */
+
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined) || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_state_t__code__defined) || \
+ 0 || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined) || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined) || \
+ 0
+ if (In0P->NDR.float_rep != NDR_record.float_rep) {
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_t__exception(&In0P->exception, In0P->NDR.float_rep);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__code__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.float_rep);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.float_rep, In1P->old_stateCnt);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined */
+ }
+#endif /* defined(__NDR_convert__float_rep...) */
+
+ return MACH_MSG_SUCCESS;
+}
+#endif /* !defined(__MIG_check__Request__exception_raise_state_t__defined) */
+#endif /* __MIG_check__Request__exc_subsystem__ */
+#endif /* ( __MigTypeCheck || __NDR_convert__ ) */
+
+
+/* Routine exception_raise_state */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif /* mig_external */
+kern_return_t breakpad_exception_raise_state
+(
+ mach_port_t exception_port,
+ exception_type_t exception,
+ const exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ const thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+);
+
+/* Routine exception_raise_state */
+mig_internal novalue _Xexception_raise_state
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ int flavor;
+ mach_msg_type_number_t old_stateCnt;
+ natural_t old_state[144];
+ mach_msg_trailer_t trailer;
+ } Request;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+ typedef __Request__exception_raise_state_t __Request;
+ typedef __Reply__exception_raise_state_t Reply;
+
+ /*
+ * typedef struct {
+ * mach_msg_header_t Head;
+ * NDR_record_t NDR;
+ * kern_return_t RetCode;
+ * } mig_reply_error_t;
+ */
+
+ Request *In0P = (Request *) InHeadP;
+ Request *In1P;
+ Reply *OutP = (Reply *) OutHeadP;
+#ifdef __MIG_check__Request__exception_raise_state_t__defined
+ kern_return_t check_result;
+#endif /* __MIG_check__Request__exception_raise_state_t__defined */
+
+ __DeclareRcvRpc(2402, "exception_raise_state")
+ __BeforeRcvRpc(2402, "exception_raise_state")
+
+#if defined(__MIG_check__Request__exception_raise_state_t__defined)
+ check_result = __MIG_check__Request__exception_raise_state_t((__Request *)In0P, (__Request **)&In1P);
+ if (check_result != MACH_MSG_SUCCESS)
+ { MIG_RETURN_ERROR(OutP, check_result); }
+#endif /* defined(__MIG_check__Request__exception_raise_state_t__defined) */
+
+ OutP->new_stateCnt = 144;
+
+ OutP->RetCode = breakpad_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
+ if (OutP->RetCode != KERN_SUCCESS) {
+ MIG_RETURN_ERROR(OutP, OutP->RetCode);
+ }
+
+ OutP->NDR = NDR_record;
+
+
+ OutP->flavor = In1P->flavor;
+ OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 576) + (((4 * OutP->new_stateCnt)));
+
+ __AfterRcvRpc(2402, "exception_raise_state")
+}
+
+#if ( __MigTypeCheck || __NDR_convert__ )
+#if __MIG_check__Request__exc_subsystem__
+#if !defined(__MIG_check__Request__exception_raise_state_identity_t__defined)
+#define __MIG_check__Request__exception_raise_state_identity_t__defined
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#if defined(__NDR_convert__int_rep__exc__exception_type_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__exception_type_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__int_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__int_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#if defined(__NDR_convert__int_rep__exc__exception_data_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__int_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exception_data_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__int_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exc__integer_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__exc__integer_t)
+#elif defined(__NDR_convert__int_rep__integer_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__integer_t)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__exc__int32_t)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined
+#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(a, f) \
+ __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(a, f) \
+ __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined
+#if defined(__NDR_convert__int_rep__exc__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__int_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__int__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__int_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__int_rep__exc__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__int32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__int_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#if defined(__NDR_convert__int_rep__exc__thread_state_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__int_rep__exc__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__thread_state_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__int_rep__exc__natural_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__exc__natural_t)
+#elif defined(__NDR_convert__int_rep__natural_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t)
+#elif defined(__NDR_convert__int_rep__exc__uint32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__exc__uint32_t)
+#elif defined(__NDR_convert__int_rep__uint32_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined */
+
+#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined
+#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(a, f) \
+ __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined)
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined
+#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(a, f) \
+ __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#if defined(__NDR_convert__char_rep__exc__exception_type_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__exception_type_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__char_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__char_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#if defined(__NDR_convert__char_rep__exc__exception_data_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__char_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exception_data_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__char_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exc__integer_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__exc__integer_t)
+#elif defined(__NDR_convert__char_rep__integer_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__integer_t)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__exc__int32_t)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined
+#if defined(__NDR_convert__char_rep__exc__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__char_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__int__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__char_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__char_rep__exc__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__char_rep__int32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__char_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined */
+
+#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#if defined(__NDR_convert__char_rep__exc__thread_state_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__char_rep__exc__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__thread_state_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__char_rep__exc__natural_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__exc__natural_t)
+#elif defined(__NDR_convert__char_rep__natural_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t)
+#elif defined(__NDR_convert__char_rep__exc__uint32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__exc__uint32_t)
+#elif defined(__NDR_convert__char_rep__uint32_t__defined)
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#if defined(__NDR_convert__float_rep__exc__exception_type_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__exception_type_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__float_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \
+ __NDR_convert__float_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#if defined(__NDR_convert__float_rep__exc__exception_data_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__float_rep__exc__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exception_data_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__float_rep__exception_data_t((exception_data_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exc__integer_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__exc__integer_t)
+#elif defined(__NDR_convert__float_rep__integer_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__integer_t)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__exc__int32_t)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \
+ __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__int32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined
+#if defined(__NDR_convert__float_rep__exc__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__float_rep__exc__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__int__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__float_rep__int((int *)(a), f)
+#elif defined(__NDR_convert__float_rep__exc__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f)
+#elif defined(__NDR_convert__float_rep__int32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \
+ __NDR_convert__float_rep__int32_t((int32_t *)(a), f)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined */
+
+#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#if defined(__NDR_convert__float_rep__exc__thread_state_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__float_rep__exc__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__thread_state_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c)
+#elif defined(__NDR_convert__float_rep__exc__natural_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__exc__natural_t)
+#elif defined(__NDR_convert__float_rep__natural_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t)
+#elif defined(__NDR_convert__float_rep__exc__uint32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__exc__uint32_t)
+#elif defined(__NDR_convert__float_rep__uint32_t__defined)
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined
+#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \
+ __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t)
+#endif /* defined(__NDR_convert__*__defined) */
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined */
+
+
+mig_internal kern_return_t __MIG_check__Request__exception_raise_state_identity_t(__attribute__((__unused__)) __Request__exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_identity_t **In1PP)
+{
+
+ typedef __Request__exception_raise_state_identity_t __Request;
+ __Request *In1P;
+#if __MigTypeCheck
+ unsigned int msgh_size;
+#endif /* __MigTypeCheck */
+ unsigned int msgh_size_delta;
+
+#if __MigTypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
+ (In0P->msgh_body.msgh_descriptor_count != 2) ||
+ (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))
+)
+ return MIG_BAD_ARGUMENTS;
+#endif /* __MigTypeCheck */
+
+#if __MigTypeCheck
+ if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
+ In0P->thread.disposition != 17)
+ return MIG_TYPE_ERROR;
+#endif /* __MigTypeCheck */
+
+#if __MigTypeCheck
+ if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
+ In0P->task.disposition != 17)
+ return MIG_TYPE_ERROR;
+#endif /* __MigTypeCheck */
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep)
+ __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined */
+ msgh_size_delta = (4 * In0P->codeCnt);
+#if __MigTypeCheck
+ if (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584) + msgh_size_delta)
+ return MIG_BAD_ARGUMENTS;
+ msgh_size -= msgh_size_delta;
+#endif /* __MigTypeCheck */
+
+ *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8);
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep)
+ __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined */
+#if __MigTypeCheck
+ if (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 584) + ((4 * In1P->old_stateCnt)))
+ return MIG_BAD_ARGUMENTS;
+#endif /* __MigTypeCheck */
+
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined) || \
+ defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined)
+ if (In0P->NDR.int_rep != NDR_record.int_rep) {
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.int_rep);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined */
+#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined)
+ __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.int_rep, In1P->old_stateCnt);
+#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined */
+ }
+#endif /* defined(__NDR_convert__int_rep...) */
+
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined) || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined) || \
+ 0 || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined) || \
+ defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined) || \
+ 0
+ if (In0P->NDR.char_rep != NDR_record.char_rep) {
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.char_rep);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.char_rep);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined */
+#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined)
+ __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.char_rep, In1P->old_stateCnt);
+#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined */
+ }
+#endif /* defined(__NDR_convert__char_rep...) */
+
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined) || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined) || \
+ 0 || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined) || \
+ defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined) || \
+ 0
+ if (In0P->NDR.float_rep != NDR_record.float_rep) {
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.float_rep);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.float_rep);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined */
+#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined)
+ __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.float_rep, In1P->old_stateCnt);
+#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined */
+ }
+#endif /* defined(__NDR_convert__float_rep...) */
+
+ return MACH_MSG_SUCCESS;
+}
+#endif /* !defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */
+#endif /* __MIG_check__Request__exc_subsystem__ */
+#endif /* ( __MigTypeCheck || __NDR_convert__ ) */
+
+
+/* Routine exception_raise_state_identity */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif /* mig_external */
+kern_return_t breakpad_exception_raise_state_identity
+(
+ mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+);
+
+/* Routine exception_raise_state_identity */
+mig_internal novalue _Xexception_raise_state_identity
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ int flavor;
+ mach_msg_type_number_t old_stateCnt;
+ natural_t old_state[144];
+ mach_msg_trailer_t trailer;
+ } Request;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+ typedef __Request__exception_raise_state_identity_t __Request;
+ typedef __Reply__exception_raise_state_identity_t Reply;
+
+ /*
+ * typedef struct {
+ * mach_msg_header_t Head;
+ * NDR_record_t NDR;
+ * kern_return_t RetCode;
+ * } mig_reply_error_t;
+ */
+
+ Request *In0P = (Request *) InHeadP;
+ Request *In1P;
+ Reply *OutP = (Reply *) OutHeadP;
+#ifdef __MIG_check__Request__exception_raise_state_identity_t__defined
+ kern_return_t check_result;
+#endif /* __MIG_check__Request__exception_raise_state_identity_t__defined */
+
+ __DeclareRcvRpc(2403, "exception_raise_state_identity")
+ __BeforeRcvRpc(2403, "exception_raise_state_identity")
+
+#if defined(__MIG_check__Request__exception_raise_state_identity_t__defined)
+ check_result = __MIG_check__Request__exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P);
+ if (check_result != MACH_MSG_SUCCESS)
+ { MIG_RETURN_ERROR(OutP, check_result); }
+#endif /* defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */
+
+ OutP->new_stateCnt = 144;
+
+ OutP->RetCode = breakpad_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
+ if (OutP->RetCode != KERN_SUCCESS) {
+ MIG_RETURN_ERROR(OutP, OutP->RetCode);
+ }
+
+ OutP->NDR = NDR_record;
+
+
+ OutP->flavor = In1P->flavor;
+ OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 576) + (((4 * OutP->new_stateCnt)));
+
+ __AfterRcvRpc(2403, "exception_raise_state_identity")
+}
+
+
+extern boolean_t exc_server(
+ mach_msg_header_t *InHeadP,
+ mach_msg_header_t *OutHeadP);
+
+extern mig_routine_t exc_server_routine(
+ mach_msg_header_t *InHeadP);
+
+
+/* Description of this subsystem, for use in direct RPC */
+const struct breakpad_exc_subsystem {
+ mig_server_routine_t server; /* Server routine */
+ mach_msg_id_t start; /* Min routine number */
+ mach_msg_id_t end; /* Max routine number + 1 */
+ unsigned int maxsize; /* Max msg size */
+ vm_address_t reserved; /* Reserved */
+ struct routine_descriptor /*Array of routine descriptors */
+ routine[3];
+} breakpad_exc_subsystem = {
+ exc_server_routine,
+ 2401,
+ 2404,
+ (mach_msg_size_t)sizeof(union __ReplyUnion__breakpad_exc_subsystem),
+ (vm_address_t)0,
+ {
+ { (mig_impl_routine_t) 0,
+ (mig_stub_routine_t) _Xexception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_t)},
+ { (mig_impl_routine_t) 0,
+ (mig_stub_routine_t) _Xexception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_t)},
+ { (mig_impl_routine_t) 0,
+ (mig_stub_routine_t) _Xexception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_identity_t)},
+ }
+};
+
+mig_external boolean_t exc_server
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ /*
+ * typedef struct {
+ * mach_msg_header_t Head;
+ * NDR_record_t NDR;
+ * kern_return_t RetCode;
+ * } mig_reply_error_t;
+ */
+
+ register mig_routine_t routine;
+
+ OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
+ OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
+ /* Minimal size: routine() will update it if different */
+ OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
+ OutHeadP->msgh_local_port = MACH_PORT_NULL;
+ OutHeadP->msgh_id = InHeadP->msgh_id + 100;
+
+ if ((InHeadP->msgh_id > 2403) || (InHeadP->msgh_id < 2401) ||
+ ((routine = breakpad_exc_subsystem.routine[InHeadP->msgh_id - 2401].stub_routine) == 0)) {
+ ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
+ ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
+ return FALSE;
+ }
+ (*routine) (InHeadP, OutHeadP);
+ return TRUE;
+}
+
+mig_external mig_routine_t exc_server_routine
+ (mach_msg_header_t *InHeadP)
+{
+ register int msgh_id;
+
+ msgh_id = InHeadP->msgh_id - 2401;
+
+ if ((msgh_id > 2) || (msgh_id < 0))
+ return 0;
+
+ return breakpad_exc_subsystem.routine[msgh_id].stub_routine;
+}
Added: trunk/google-breakpad/src/client/mac/handler/breakpad_exc_server.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/mac/handler/breakpad_exc_server.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,258 @@
+#ifndef _exc_user_
+#define _exc_user_
+
+/* Module exc */
+
+#include <string.h>
+#include <mach/ndr.h>
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/notify.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+#include <mach/port.h>
+
+#ifdef AUTOTEST
+#ifndef FUNCTION_PTR_T
+#define FUNCTION_PTR_T
+typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
+typedef struct {
+ char *name;
+ function_ptr_t function;
+} function_table_entry;
+typedef function_table_entry *function_table_t;
+#endif /* FUNCTION_PTR_T */
+#endif /* AUTOTEST */
+
+#ifndef exc_MSG_COUNT
+#define exc_MSG_COUNT 3
+#endif /* exc_MSG_COUNT */
+
+#include <mach/std_types.h>
+#include <mach/mig.h>
+#include <mach/mig.h>
+#include <mach/mach_types.h>
+
+#ifdef __BeforeMigUserHeader
+__BeforeMigUserHeader
+#endif /* __BeforeMigUserHeader */
+
+#include <sys/cdefs.h>
+__BEGIN_DECLS
+
+
+/* Routine exception_raise */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif /* mig_external */
+kern_return_t exception_raise
+(
+ mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt
+);
+
+/* Routine exception_raise_state */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif /* mig_external */
+kern_return_t exception_raise_state
+(
+ mach_port_t exception_port,
+ exception_type_t exception,
+ const exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ const thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+);
+
+/* Routine exception_raise_state_identity */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif /* mig_external */
+kern_return_t exception_raise_state_identity
+(
+ mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+);
+
+__END_DECLS
+
+/********************** Caution **************************/
+/* The following data types should be used to calculate */
+/* maximum message sizes only. The actual message may be */
+/* smaller, and the position of the arguments within the */
+/* message layout may vary from what is presented here. */
+/* For example, if any of the arguments are variable- */
+/* sized, and less than the maximum is sent, the data */
+/* will be packed tight in the actual message to reduce */
+/* the presence of holes. */
+/********************** Caution **************************/
+
+/* typedefs for all requests */
+
+#ifndef __Request__exc_subsystem__defined
+#define __Request__exc_subsystem__defined
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ } __Request__exception_raise_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ int flavor;
+ mach_msg_type_number_t old_stateCnt;
+ natural_t old_state[144];
+ } __Request__exception_raise_state_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ integer_t code[2];
+ int flavor;
+ mach_msg_type_number_t old_stateCnt;
+ natural_t old_state[144];
+ } __Request__exception_raise_state_identity_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+#endif /* !__Request__exc_subsystem__defined */
+
+/* union of all requests */
+
+#ifndef __RequestUnion__exc_subsystem__defined
+#define __RequestUnion__exc_subsystem__defined
+union __RequestUnion__exc_subsystem {
+ __Request__exception_raise_t Request_exception_raise;
+ __Request__exception_raise_state_t Request_exception_raise_state;
+ __Request__exception_raise_state_identity_t Request_exception_raise_state_identity;
+};
+#endif /* !__RequestUnion__exc_subsystem__defined */
+/* typedefs for all replies */
+
+#ifndef __Reply__exc_subsystem__defined
+#define __Reply__exc_subsystem__defined
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ } __Reply__exception_raise_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ int flavor;
+ mach_msg_type_number_t new_stateCnt;
+ natural_t new_state[144];
+ } __Reply__exception_raise_state_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+
+#ifdef __MigPackStructs
+#pragma pack(4)
+#endif
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ int flavor;
+ mach_msg_type_number_t new_stateCnt;
+ natural_t new_state[144];
+ } __Reply__exception_raise_state_identity_t;
+#ifdef __MigPackStructs
+#pragma pack()
+#endif
+#endif /* !__Reply__exc_subsystem__defined */
+
+/* union of all replies */
+
+#ifndef __ReplyUnion__exc_subsystem__defined
+#define __ReplyUnion__exc_subsystem__defined
+union __ReplyUnion__exc_subsystem {
+ __Reply__exception_raise_t Reply_exception_raise;
+ __Reply__exception_raise_state_t Reply_exception_raise_state;
+ __Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
+};
+#endif /* !__RequestUnion__exc_subsystem__defined */
+
+#ifndef subsystem_to_name_map_exc
+#define subsystem_to_name_map_exc \
+ { "exception_raise", 2401 },\
+ { "exception_raise_state", 2402 },\
+ { "exception_raise_state_identity", 2403 }
+#endif
+
+#ifdef __AfterMigUserHeader
+__AfterMigUserHeader
+#endif /* __AfterMigUserHeader */
+
+#endif /* _exc_user_ */
Added: trunk/google-breakpad/src/client/mac/handler/breakpad_nlist_64.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/mac/handler/breakpad_nlist_64.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+
+/* nealsid:
+ * This file was copied from libc/gen/nlist.c from Darwin's source code
+ * The version of nlist used as a base is from 10.5.2, libc-498
+ * http://www.opensource.apple.com/darwinsource/10.5.2/Libc-498/gen/nlist.c
+ *
+ * The full tarball is at:
+ * http://www.opensource.apple.com/darwinsource/tarballs/apsl/Libc-498.tar.gz
+ *
+ * I've modified it to be compatible with 64-bit images. However,
+ * 32-bit compatibility has not been retained.
+*/
+
+#ifdef __LP64__
+
+#include <mach-o/nlist.h>
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include "breakpad_nlist_64.h"
+#include <TargetConditionals.h>
+#include <stdio.h>
+#include <mach/mach.h>
+
+/* Stuff lifted from <a.out.h> and <sys/exec.h> since they are gone */
+/*
+ * Header prepended to each a.out file.
+ */
+struct exec {
+ unsigned short a_machtype; /* machine type */
+ unsigned short a_magic; /* magic number */
+ unsigned long a_text; /* size of text segment */
+ unsigned long a_data; /* size of initialized data */
+ unsigned long a_bss; /* size of uninitialized data */
+ unsigned long a_syms; /* size of symbol table */
+ unsigned long a_entry; /* entry point */
+ unsigned long a_trsize; /* size of text relocation */
+ unsigned long a_drsize; /* size of data relocation */
+};
+
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+#define N_BADMAG(x) \
+ (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
+#define N_TXTOFF(x) \
+ ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec))
+#define N_SYMOFF(x) \
+ (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize)
+
+int
+__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames);
+
+/*
+ * nlist - retreive attributes from name list (string table version)
+ */
+
+int
+breakpad_nlist_64(const char *name,
+ breakpad_nlist *list,
+ const char **symbolNames) {
+ int fd, n;
+
+ fd = open(name, O_RDONLY, 0);
+ if (fd < 0)
+ return (-1);
+ n = __breakpad_fdnlist_64(fd, list, symbolNames);
+ (void)close(fd);
+ return (n);
+}
+
+/* Note: __fdnlist() is called from kvm_nlist in libkvm's kvm.c */
+
+int
+__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames) {
+ register breakpad_nlist *p, *q;
+ breakpad_nlist space[BUFSIZ/sizeof (breakpad_nlist)];
+
+ const register char *s1, *s2;
+ register int n, m;
+ int maxlen, nreq;
+ off_t sa; /* symbol address */
+ off_t ss; /* start of strings */
+ struct exec buf;
+ unsigned arch_offset = 0;
+
+ maxlen = 500;
+ for (q = list, nreq = 0;
+ symbolNames[q-list] && symbolNames[q-list][0];
+ q++, nreq++) {
+
+ q->n_type = 0;
+ q->n_value = 0;
+ q->n_desc = 0;
+ q->n_sect = 0;
+ q->n_un.n_strx = 0;
+ }
+
+ if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) ||
+ (N_BADMAG(buf) && *((long *)&buf) != MH_MAGIC &&
+ NXSwapBigLongToHost(*((long *)&buf)) != FAT_MAGIC) &&
+ /* nealsid: The following is the big-endian ppc64 check */
+ (*((uint32_t*)&buf)) != FAT_MAGIC) {
+ return (-1);
+ }
+
+ /* Deal with fat file if necessary */
+ if (NXSwapBigLongToHost(*((long *)&buf)) == FAT_MAGIC ||
+ /* nealsid: The following is the big-endian ppc64 check */
+ *((int*)&buf) == FAT_MAGIC) {
+ struct host_basic_info hbi;
+ struct fat_header fh;
+ struct fat_arch *fat_archs, *fap;
+ unsigned i;
+ host_t host;
+
+ /* Get our host info */
+ host = mach_host_self();
+ i = HOST_BASIC_INFO_COUNT;
+ kern_return_t kr;
+ if ((kr=host_info(host, HOST_BASIC_INFO,
+ (host_info_t)(&hbi), &i)) != KERN_SUCCESS) {
+ return (-1);
+ }
+ mach_port_deallocate(mach_task_self(), host);
+
+ /* Read in the fat header */
+ lseek(fd, 0, SEEK_SET);
+ if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) {
+ return (-1);
+ }
+
+ /* Convert fat_narchs to host byte order */
+ fh.nfat_arch = NXSwapBigLongToHost(fh.nfat_arch);
+
+ /* Read in the fat archs */
+ fat_archs = (struct fat_arch *)malloc(fh.nfat_arch *
+ sizeof(struct fat_arch));
+ if (fat_archs == NULL) {
+ return (-1);
+ }
+ if (read(fd, (char *)fat_archs,
+ sizeof(struct fat_arch) * fh.nfat_arch) !=
+ sizeof(struct fat_arch) * fh.nfat_arch) {
+ free(fat_archs);
+ return (-1);
+ }
+
+ /*
+ * Convert archs to host byte ordering (a constraint of
+ * cpusubtype_getbestarch()
+ */
+ for (i = 0; i < fh.nfat_arch; i++) {
+ fat_archs[i].cputype =
+ NXSwapBigLongToHost(fat_archs[i].cputype);
+ fat_archs[i].cpusubtype =
+ NXSwapBigLongToHost(fat_archs[i].cpusubtype);
+ fat_archs[i].offset =
+ NXSwapBigLongToHost(fat_archs[i].offset);
+ fat_archs[i].size =
+ NXSwapBigLongToHost(fat_archs[i].size);
+ fat_archs[i].align =
+ NXSwapBigLongToHost(fat_archs[i].align);
+ }
+
+ fap = NULL;
+ for (i = 0; i < fh.nfat_arch; i++) {
+ /* nealsid: Although the original Apple code uses host_info */
+ /* to retrieve the CPU type, the host_info will still return */
+ /* CPU_TYPE_X86 even if running as an x86_64 binary. Given that */
+ /* this code isn't necessary on i386, I've decided to hardcode */
+ /* looking for a 64-bit binary */
+#if TARGET_CPU_X86_64
+ if (fat_archs[i].cputype == CPU_TYPE_X86_64) {
+#elif TARGET_CPU_PPC64
+ if (fat_archs[i].cputype == CPU_TYPE_POWERPC64) {
+#else
+#error undefined cpu!
+ {
+#endif
+ fap = &fat_archs[i];
+ break;
+ }
+ }
+
+ if (!fap) {
+ free(fat_archs);
+ return (-1);
+ }
+ arch_offset = fap->offset;
+ free(fat_archs);
+
+ /* Read in the beginning of the architecture-specific file */
+ lseek(fd, arch_offset, SEEK_SET);
+ if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) {
+ return (-1);
+ }
+ }
+
+ if (*((int *)&buf) == MH_MAGIC_64) {
+ struct mach_header_64 mh;
+ struct load_command *load_commands, *lcp;
+ struct symtab_command *stp;
+ long i;
+
+ lseek(fd, arch_offset, SEEK_SET);
+ if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) {
+ return (-1);
+ }
+ load_commands = (struct load_command *)malloc(mh.sizeofcmds);
+ if (load_commands == NULL) {
+ return (-1);
+ }
+ if (read(fd, (char *)load_commands, mh.sizeofcmds) !=
+ mh.sizeofcmds) {
+ free(load_commands);
+ return (-1);
+ }
+ stp = NULL;
+ lcp = load_commands;
+ // nealsid:iterate through all load commands, looking for
+ // LC_SYMTAB load command
+ for (i = 0; i < mh.ncmds; i++) {
+ if (lcp->cmdsize % sizeof(long) != 0 ||
+ lcp->cmdsize <= 0 ||
+ (char *)lcp + lcp->cmdsize >
+ (char *)load_commands + mh.sizeofcmds) {
+ free(load_commands);
+ return (-1);
+ }
+ if (lcp->cmd == LC_SYMTAB) {
+ if (lcp->cmdsize !=
+ sizeof(struct symtab_command)) {
+ free(load_commands);
+ return (-1);
+ }
+ stp = (struct symtab_command *)lcp;
+ break;
+ }
+ lcp = (struct load_command *)
+ ((char *)lcp + lcp->cmdsize);
+ }
+ if (stp == NULL) {
+ free(load_commands);
+ return (-1);
+ }
+ // sa points to the beginning of the symbol table
+ sa = stp->symoff + arch_offset;
+ // ss points to the beginning of the string table
+ ss = stp->stroff + arch_offset;
+ // n is the number of bytes in the symbol table
+ // each symbol table entry is an nlist structure
+ n = stp->nsyms * sizeof(breakpad_nlist);
+ free(load_commands);
+ }
+ else {
+ sa = N_SYMOFF(buf) + arch_offset;
+ ss = sa + buf.a_syms + arch_offset;
+ n = buf.a_syms;
+ }
+
+ lseek(fd, sa, SEEK_SET);
+
+ // the algorithm here is to read the nlist entries in m-sized
+ // chunks into q. q is then iterated over. for each entry in q,
+ // use the string table index(q->n_un.n_strx) to read the symbol
+ // name, then scan the nlist entries passed in by the user(via p),
+ // and look for a match
+ while (n) {
+ long savpos;
+
+ m = sizeof (space);
+ if (n < m)
+ m = n;
+ if (read(fd, (char *)space, m) != m)
+ break;
+ n -= m;
+ savpos = lseek(fd, 0, SEEK_CUR);
+ for (q = space; (m -= sizeof(breakpad_nlist)) >= 0; q++) {
+ char nambuf[BUFSIZ];
+
+ if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
+ continue;
+
+ // seek to the location in the binary where the symbol
+ // name is stored & read it into memory
+ lseek(fd, ss+q->n_un.n_strx, SEEK_SET);
+ read(fd, nambuf, maxlen+1);
+ s2 = nambuf;
+ for (p = list;
+ symbolNames[p-list] &&
+ symbolNames[p-list][0];
+ p++) {
+ // get the symbol name the user has passed in that
+ // corresponds to the nlist entry that we're looking at
+ s1 = symbolNames[p - list];
+ while (*s1) {
+ if (*s1++ != *s2++)
+ goto cont;
+ }
+ if (*s2)
+ goto cont;
+
+ p->n_value = q->n_value;
+ p->n_type = q->n_type;
+ p->n_desc = q->n_desc;
+ p->n_sect = q->n_sect;
+ p->n_un.n_strx = q->n_un.n_strx;
+ if (--nreq == 0)
+ return (nreq);
+
+ break;
+ cont: ;
+ }
+ }
+ lseek(fd, savpos, SEEK_SET);
+ }
+ return (nreq);
+ }
+
+#endif /* __LP64__ */
Added: trunk/google-breakpad/src/client/mac/handler/breakpad_nlist_64.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/mac/handler/breakpad_nlist_64.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,43 @@
+// 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.
+
+// breakpad_nlist.h
+//
+// This file is meant to provide a header for clients of the modified
+// nlist function implemented to work on 64-bit.
+
+#ifndef CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
+
+typedef struct nlist_64 breakpad_nlist;
+
+int
+breakpad_nlist_64(const char *name,
+ breakpad_nlist *list,
+ const char **symbolNames);
+
+#endif /* CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ */
Modified: trunk/google-breakpad/src/client/mac/handler/dynamic_images.cc
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/dynamic_images.cc (original)
+++ trunk/google-breakpad/src/client/mac/handler/dynamic_images.cc Sun Oct 19 13:26:38 2008
@@ -33,11 +33,14 @@
#include <stdio.h>
}
+#include "breakpad_nlist_64.h"
+#include <dlfcn.h>
+#include <mach/mach_vm.h>
#include <algorithm>
#include "client/mac/handler/dynamic_images.h"
namespace google_breakpad {
-
+
//==============================================================================
// Returns the size of the memory region containing |address| and the
// number of bytes from |address| to the end of the region.
@@ -46,27 +49,30 @@
// first in order to handle cases when we're reading strings and they
// straddle two vm regions.
//
-static vm_size_t GetMemoryRegionSize(task_port_t target_task,
- const void* address,
- vm_size_t *size_to_end) {
- vm_address_t region_base = (vm_address_t)address;
- vm_size_t region_size;
+static mach_vm_size_t GetMemoryRegionSize(task_port_t target_task,
+ const void* address,
+ mach_vm_size_t *size_to_end) {
+ mach_vm_address_t region_base = (mach_vm_address_t)address;
+ mach_vm_size_t region_size;
natural_t nesting_level = 0;
- vm_region_submap_info submap_info;
- mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT;
-
+ vm_region_submap_info_64 submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
// Get information about the vm region containing |address|
- kern_return_t result =
- vm_region_recurse(target_task,
- ®ion_base,
- ®ion_size,
- &nesting_level,
- reinterpret_cast<vm_region_recurse_info_t>(&submap_info),
- &info_count);
-
+ vm_region_recurse_info_t region_info;
+ region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info);
+
+ kern_return_t result =
+ mach_vm_region_recurse(target_task,
+ ®ion_base,
+ ®ion_size,
+ &nesting_level,
+ region_info,
+ &info_count);
+
if (result == KERN_SUCCESS) {
// Get distance from |address| to the end of this region
- *size_to_end = region_base + region_size -(vm_address_t)address;
+ *size_to_end = region_base + region_size -(mach_vm_address_t)address;
// If we want to handle strings as long as 4096 characters we may need
// to check if there's a vm region immediately following the first one.
@@ -74,20 +80,19 @@
// of the second region.
if (*size_to_end < 4096) {
// Second region starts where the first one ends
- vm_address_t region_base2 =
- (vm_address_t)(region_base + region_size);
- vm_size_t region_size2;
+ mach_vm_address_t region_base2 =
+ (mach_vm_address_t)(region_base + region_size);
+ mach_vm_size_t region_size2;
// Get information about the following vm region
- result =
- vm_region_recurse(
- target_task,
- ®ion_base2,
- ®ion_size2,
- &nesting_level,
- reinterpret_cast<vm_region_recurse_info_t>(&submap_info),
- &info_count);
-
+ result =
+ mach_vm_region_recurse(target_task,
+ ®ion_base2,
+ ®ion_size2,
+ &nesting_level,
+ region_info,
+ &info_count);
+
// Extend region_size to go all the way to the end of the 2nd region
if (result == KERN_SUCCESS
&& region_base2 == region_base + region_size) {
@@ -95,13 +100,13 @@
}
}
- *size_to_end = region_base + region_size -(vm_address_t)address;
+ *size_to_end = region_base + region_size -(mach_vm_address_t)address;
} else {
region_size = 0;
*size_to_end = 0;
}
-
- return region_size;
+
+ return region_size;
}
#define kMaxStringLength 8192
@@ -115,17 +120,18 @@
// The problem is we don't know how much to read until we know how long
// the string is. And we don't know how long the string is, until we've read
// the memory! So, we'll try to read kMaxStringLength bytes
- // (or as many bytes as we can until we reach the end of the vm region).
- vm_size_t size_to_end;
+ // (or as many bytes as we can until we reach the end of the vm region).
+ mach_vm_size_t size_to_end;
GetMemoryRegionSize(target_task, address, &size_to_end);
-
+
if (size_to_end > 0) {
- vm_size_t size_to_read =
+ mach_vm_size_t size_to_read =
size_to_end > kMaxStringLength ? kMaxStringLength : size_to_end;
- return ReadTaskMemory(target_task, address, size_to_read);
+ kern_return_t kr;
+ return ReadTaskMemory(target_task, address, size_to_read, &kr);
}
-
+
return NULL;
}
@@ -134,29 +140,46 @@
// and should be freed by the caller.
void* ReadTaskMemory(task_port_t target_task,
const void* address,
- size_t length) {
+ size_t length,
+ kern_return_t *kr) {
void* result = NULL;
- vm_address_t page_address = reinterpret_cast<vm_address_t>(address) & (-4096);
- vm_address_t last_page_address =
- (reinterpret_cast<vm_address_t>(address) + length + 4095) & (-4096);
- vm_size_t page_size = last_page_address - page_address;
+ int systemPageSize = getpagesize();
+
+ // use the negative of the page size for the mask to find the page address
+ mach_vm_address_t page_address =
+ reinterpret_cast<mach_vm_address_t>(address) & (-systemPageSize);
+
+ mach_vm_address_t last_page_address =
+ (reinterpret_cast<mach_vm_address_t>(address) + length +
+ (systemPageSize - 1)) & (-systemPageSize);
+
+ mach_vm_size_t page_size = last_page_address - page_address;
uint8_t* local_start;
uint32_t local_length;
- kern_return_t r = vm_read(target_task,
- page_address,
- page_size,
- reinterpret_cast<vm_offset_t*>(&local_start),
- &local_length);
+ kern_return_t r;
+
+ r = mach_vm_read(target_task,
+ page_address,
+ page_size,
+ reinterpret_cast<vm_offset_t*>(&local_start),
+ &local_length);
+
+
+ if (kr != NULL) {
+ *kr = r;
+ }
if (r == KERN_SUCCESS) {
result = malloc(length);
if (result != NULL) {
- memcpy(result, &local_start[(uint32_t)address - page_address], length);
+ memcpy(result,
+ &local_start[(mach_vm_address_t)address - page_address],
+ length);
}
- vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_length);
+ mach_vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_length);
}
-
+
return result;
}
@@ -165,21 +188,41 @@
//==============================================================================
// Initializes vmaddr_, vmsize_, and slide_
void DynamicImage::CalculateMemoryInfo() {
- mach_header *header = GetMachHeader();
+ breakpad_mach_header *header = GetMachHeader();
+
+ // unless we can process the header, ensure that calls to
+ // IsValid() will return false
+ vmaddr_ = 0;
+ vmsize_ = 0;
+ slide_ = 0;
+
+#if __LP64__
+ if(header->magic != MH_MAGIC_64) {
+ return;
+ }
+#else
+ if(header->magic != MH_MAGIC) {
+ return;
+ }
+#endif
const struct load_command *cmd =
reinterpret_cast<const struct load_command *>(header + 1);
for (unsigned int i = 0; cmd && (i < header->ncmds); ++i) {
+#ifdef __LP64__
+ if (cmd->cmd == LC_SEGMENT_64) {
+#else
if (cmd->cmd == LC_SEGMENT) {
- const struct segment_command *seg =
- reinterpret_cast<const struct segment_command *>(cmd);
+#endif
+ const breakpad_mach_segment_command *seg =
+ reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
if (!strcmp(seg->segname, "__TEXT")) {
vmaddr_ = seg->vmaddr;
vmsize_ = seg->vmsize;
slide_ = 0;
-
+
if (seg->fileoff == 0 && seg->filesize != 0) {
slide_ = (uintptr_t)GetLoadAddress() - (uintptr_t)seg->vmaddr;
}
@@ -190,11 +233,7 @@
cmd = reinterpret_cast<const struct load_command *>
(reinterpret_cast<const char *>(cmd) + cmd->cmdsize);
}
-
- // we failed - a call to IsValid() will return false
- vmaddr_ = 0;
- vmsize_ = 0;
- slide_ = 0;
+
}
void DynamicImage::Print() {
@@ -203,11 +242,11 @@
path = "(unknown)";
}
printf("%p: %s\n", GetLoadAddress(), path);
- mach_header *header = GetMachHeader();
+ breakpad_mach_header *header = GetMachHeader();
MachHeader(*header).Print();
printf("vmaddr\t\t: %p\n", reinterpret_cast<void*>(GetVMAddr()));
- printf("vmsize\t\t: %d\n", GetVMSize());
- printf("slide\t\t: %d\n", GetVMAddrSlide());
+ printf("vmsize\t\t: %llu\n", GetVMSize());
+ printf("slide\t\t: %td\n", GetVMAddrSlide());
}
#pragma mark -
@@ -219,9 +258,12 @@
ReadImageInfoForTask();
}
-//==============================================================================
-// This code was written using dyld_debug.c (from Darwin) as a guide.
-void DynamicImages::ReadImageInfoForTask() {
+void* DynamicImages::GetDyldAllImageInfosPointer()
+{
+
+ const char *imageSymbolName = "_dyld_all_image_infos";
+ const char *dyldPath = "/usr/lib/dyld";
+#ifndef __LP64__
struct nlist l[8];
memset(l, 0, sizeof(l) );
@@ -229,10 +271,38 @@
// which lives in "dyld". This structure contains information about all
// of the loaded dynamic images.
struct nlist &list = l[0];
- list.n_un.n_name = const_cast<char *>("_dyld_all_image_infos");
- nlist("/usr/lib/dyld", &list);
-
- if (list.n_value) {
+ list.n_un.n_name = const_cast<char *>(imageSymbolName);
+ nlist(dyldPath,&list);
+ if(list.n_value) {
+ return reinterpret_cast<void*>(list.n_value);
+ }
+
+ return NULL;
+#else
+ struct nlist_64 l[8];
+ struct nlist_64 &list = l[0];
+
+ memset(l, 0, sizeof(l) );
+
+ const char *symbolNames[2] = { imageSymbolName, "\0" };
+
+ int invalidEntriesCount = breakpad_nlist_64(dyldPath,&list,symbolNames);
+
+ if(invalidEntriesCount != 0) {
+ return NULL;
+ }
+ assert(list.n_value);
+ return reinterpret_cast<void*>(list.n_value);
+#endif
+
+}
+//==============================================================================
+// This code was written using dyld_debug.c (from Darwin) as a guide.
+void DynamicImages::ReadImageInfoForTask() {
+ void *imageList = GetDyldAllImageInfosPointer();
+
+ if (imageList) {
+ kern_return_t kr;
// Read the structure inside of dyld that contains information about
// loaded images. We're reading from the desired task's address space.
@@ -241,8 +311,8 @@
// "dyld_debug.c" and is said to be nearly always valid.
dyld_all_image_infos *dyldInfo = reinterpret_cast<dyld_all_image_infos*>
(ReadTaskMemory(task_,
- reinterpret_cast<void*>(list.n_value),
- sizeof(dyld_all_image_infos)));
+ reinterpret_cast<void*>(imageList),
+ sizeof(dyld_all_image_infos), &kr));
if (dyldInfo) {
// number of loaded images
@@ -253,7 +323,7 @@
dyld_image_info *infoArray = reinterpret_cast<dyld_image_info*>
(ReadTaskMemory(task_,
dyldInfo->infoArray,
- count*sizeof(dyld_image_info)));
+ count*sizeof(dyld_image_info), &kr));
image_list_.reserve(count);
@@ -261,20 +331,24 @@
dyld_image_info &info = infoArray[i];
// First read just the mach_header from the image in the task.
- mach_header *header = reinterpret_cast<mach_header*>
- (ReadTaskMemory(task_, info.load_address_, sizeof(mach_header)));
+ breakpad_mach_header *header = reinterpret_cast<breakpad_mach_header*>
+ (ReadTaskMemory(task_,
+ info.load_address_,
+ sizeof(breakpad_mach_header), &kr));
if (!header)
break; // bail on this dynamic image
-
+
// Now determine the total amount we really want to read based on the
- // size of the load commands. We need the header plus all of the
+ // size of the load commands. We need the header plus all of the
// load commands.
- unsigned int header_size = sizeof(mach_header) + header->sizeofcmds;
+ unsigned int header_size =
+ sizeof(breakpad_mach_header) + header->sizeofcmds;
+
free(header);
- header = reinterpret_cast<mach_header*>
- (ReadTaskMemory(task_, info.load_address_, header_size));
+ header = reinterpret_cast<breakpad_mach_header*>
+ (ReadTaskMemory(task_, info.load_address_, header_size, &kr));
// Read the file name from the task's memory space.
char *file_path = NULL;
@@ -285,43 +359,52 @@
file_path = reinterpret_cast<char*>
(ReadTaskString(task_, info.file_path_));
}
-
+
// Create an object representing this image and add it to our list.
- DynamicImage *new_image = new DynamicImage(header,
- header_size,
- info.load_address_,
- file_path,
- info.file_mod_date_,
- task_);
+ DynamicImage *new_image;
+ new_image = new DynamicImage(header,
+ header_size,
+ (breakpad_mach_header*)info.load_address_,
+ file_path,
+ info.file_mod_date_,
+ task_);
if (new_image->IsValid()) {
image_list_.push_back(DynamicImageRef(new_image));
} else {
delete new_image;
}
-
+
if (file_path) {
free(file_path);
}
}
-
+
free(dyldInfo);
free(infoArray);
-
+
// sorts based on loading address
sort(image_list_.begin(), image_list_.end() );
+ // remove duplicates - this happens in certain strange cases
+ // You can see it in DashboardClient when Google Gadgets plugin
+ // is installed. Apple's crash reporter log and gdb "info shared"
+ // both show the same library multiple times at the same address
+
+ vector<DynamicImageRef>::iterator it = unique(image_list_.begin(),
+ image_list_.end() );
+ image_list_.erase(it, image_list_.end());
}
- }
+ }
}
//==============================================================================
DynamicImage *DynamicImages::GetExecutableImage() {
int executable_index = GetExecutableImageIndex();
-
+
if (executable_index >= 0) {
return GetImage(executable_index);
}
-
+
return NULL;
}
Modified: trunk/google-breakpad/src/client/mac/handler/dynamic_images.h
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/dynamic_images.h (original)
+++ trunk/google-breakpad/src/client/mac/handler/dynamic_images.h Sun Oct 19 13:26:38 2008
@@ -68,13 +68,22 @@
bool processDetachedFromSharedRegion;
} dyld_all_image_infos;
+// some typedefs to isolate 64/32 bit differences
+#ifdef __LP64__
+typedef mach_header_64 breakpad_mach_header;
+typedef segment_command_64 breakpad_mach_segment_command;
+#else
+typedef mach_header breakpad_mach_header;
+typedef segment_command breakpad_mach_segment_command;
+#endif
+
//==============================================================================
// A simple wrapper for a mach_header
//
// This could be fleshed out with some more interesting methods.
class MachHeader {
public:
- explicit MachHeader(const mach_header &header) : header_(header) {}
+ explicit MachHeader(const breakpad_mach_header &header) : header_(header) {}
void Print() {
printf("magic\t\t: %4x\n", header_.magic);
@@ -86,16 +95,16 @@
printf("flags\t\t: %d\n", header_.flags);
}
- mach_header header_;
+ breakpad_mach_header header_;
};
//==============================================================================
// Represents a single dynamically loaded mach-o image
class DynamicImage {
public:
- DynamicImage(mach_header *header, // we take ownership
- int header_size, // includes load commands
- mach_header *load_address,
+ DynamicImage(breakpad_mach_header *header, // we take ownership
+ int header_size, // includes load commands
+ breakpad_mach_header *load_address,
char *inFilePath,
uintptr_t image_mod_date,
mach_port_t task)
@@ -116,7 +125,7 @@
}
// Returns pointer to a local copy of the mach_header plus load commands
- mach_header *GetMachHeader() {return header_;}
+ breakpad_mach_header *GetMachHeader() {return header_;}
// Size of mach_header plus load commands
int GetHeaderSize() const {return header_size_;}
@@ -127,16 +136,16 @@
uintptr_t GetModDate() const {return file_mod_date_;}
// Actual address where the image was loaded
- mach_header *GetLoadAddress() const {return load_address_;}
+ breakpad_mach_header *GetLoadAddress() const {return load_address_;}
// Address where the image should be loaded
- uint32_t GetVMAddr() const {return vmaddr_;}
+ mach_vm_address_t GetVMAddr() const {return vmaddr_;}
// Difference between GetLoadAddress() and GetVMAddr()
ptrdiff_t GetVMAddrSlide() const {return slide_;}
// Size of the image
- uint32_t GetVMSize() const {return vmsize_;}
+ mach_vm_size_t GetVMSize() const {return vmsize_;}
// Task owning this loaded image
mach_port_t GetTask() {return task_;}
@@ -153,7 +162,7 @@
friend class DynamicImages;
// Sanity checking
- bool IsValid() {return GetVMAddr() != 0;}
+ bool IsValid() {return GetVMSize() != 0;}
// Makes local copy of file path to mach-o binary
void InitializeFilePath(char *inFilePath) {
@@ -183,23 +192,25 @@
InitializeFilePath(inInfo.GetFilePath());
// copy mach_header and load commands
- header_ = reinterpret_cast<mach_header*>(malloc(inInfo.header_size_));
+ void *headerBuffer = malloc(inInfo.header_size_);
+ header_ = reinterpret_cast<breakpad_mach_header*>(headerBuffer);
+
memcpy(header_, inInfo.header_, inInfo.header_size_);
header_size_ = inInfo.header_size_;
}
#endif
- mach_header *header_; // our local copy of the header
- int header_size_; // mach_header plus load commands
- mach_header *load_address_; // base address image is mapped into
- uint32_t vmaddr_;
- uint32_t vmsize_;
- ptrdiff_t slide_;
+ breakpad_mach_header *header_; // our local copy of the header
+ int header_size_; // mach_header plus load commands
+ breakpad_mach_header *load_address_; // base address image is mapped into
+ mach_vm_address_t vmaddr_;
+ mach_vm_size_t vmsize_;
+ ptrdiff_t slide_;
- char *file_path_; // path dyld used to load the image
- uintptr_t file_mod_date_; // time_t of image file
+ char *file_path_; // path dyld used to load the image
+ uintptr_t file_mod_date_; // time_t of image file
- mach_port_t task_;
+ mach_port_t task_;
};
//==============================================================================
@@ -211,13 +222,19 @@
class DynamicImageRef {
public:
explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
- DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {} // STL required
+ // The copy constructor is required by STL
+ DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
bool operator<(const DynamicImageRef &inRef) const {
return (*const_cast<DynamicImageRef*>(this)->p)
< (*const_cast<DynamicImageRef&>(inRef).p);
}
+ bool operator==(const DynamicImageRef &inInfo) const {
+ return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
+ (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
+ }
+
// Be just like DynamicImage*
DynamicImage *operator->() {return p;}
operator DynamicImage*() {return p;}
@@ -266,10 +283,14 @@
}
void TestPrint() {
+ const breakpad_mach_header *header;
for (int i = 0; i < (int)image_list_.size(); ++i) {
printf("dyld: %p: name = %s\n", _dyld_get_image_header(i),
- _dyld_get_image_name(i) );
- const mach_header *header = _dyld_get_image_header(i);
+ _dyld_get_image_name(i) );
+
+ const void *imageHeader = _dyld_get_image_header(i);
+ header = reinterpret_cast<const breakpad_mach_header*>(imageHeader);
+
MachHeader(*header).Print();
}
}
@@ -279,6 +300,7 @@
// Initialization
void ReadImageInfoForTask();
+ void* GetDyldAllImageInfosPointer();
mach_port_t task_;
vector<DynamicImageRef> image_list_;
@@ -286,7 +308,10 @@
// Returns a malloced block containing the contents of memory at a particular
// location in another task.
-void* ReadTaskMemory(task_port_t target_task, const void* address, size_t len);
+void* ReadTaskMemory(task_port_t target_task,
+ const void* address,
+ size_t len,
+ kern_return_t *kr);
} // namespace google_breakpad
Modified: trunk/google-breakpad/src/client/mac/handler/exception_handler.cc
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/exception_handler.cc (original)
+++ trunk/google-breakpad/src/client/mac/handler/exception_handler.cc Sun Oct 19 13:26:38 2008
@@ -137,8 +137,79 @@
mach_msg_type_number_t thread_state_count,
thread_state_t thread_state,
mach_msg_type_number_t *thread_state_count);
+
+ kern_return_t breakpad_exception_raise_state(mach_port_t exception_port,
+ exception_type_t exception,
+ const exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ const thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+ );
+
+ kern_return_t breakpad_exception_raise_state_identity(mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+ );
+
+ kern_return_t breakpad_exception_raise(mach_port_t port, mach_port_t failed_thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count);
+}
+
+
+
+kern_return_t breakpad_exception_raise_state(mach_port_t exception_port,
+ exception_type_t exception,
+ const exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ const thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+ )
+{
+ return KERN_SUCCESS;
+}
+
+kern_return_t breakpad_exception_raise_state_identity(mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ int *flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt
+ )
+{
+ return KERN_SUCCESS;
+}
+
+kern_return_t breakpad_exception_raise(mach_port_t port, mach_port_t failed_thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count) {
+ return ForwardException(task, failed_thread, exception, code, code_count);
}
+
ExceptionHandler::ExceptionHandler(const string &dump_path,
FilterCallback filter,
MinidumpCallback callback,
Modified: trunk/google-breakpad/src/client/mac/handler/minidump_generator.cc
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/minidump_generator.cc (original)
+++ trunk/google-breakpad/src/client/mac/handler/minidump_generator.cc Sun Oct 19 13:26:38 2008
@@ -30,11 +30,13 @@
#include <cstdio>
#include <mach/host_info.h>
+#include <mach/mach_vm.h>
#include <mach/vm_statistics.h>
#include <mach-o/dyld.h>
#include <mach-o/loader.h>
#include <sys/sysctl.h>
#include <sys/resource.h>
+#include <mach/mach_vm.h>
#include <CoreFoundation/CoreFoundation.h>
@@ -48,7 +50,7 @@
namespace google_breakpad {
-// constructor when generating from within the crashed process
+// constructor when generating from within the crashed process
MinidumpGenerator::MinidumpGenerator()
: exception_type_(0),
exception_code_(0),
@@ -59,8 +61,10 @@
GatherSystemInformation();
}
-// constructor when generating from a different process than the crashed process
-MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread)
+// constructor when generating from a different process than the
+// crashed process
+MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
+ mach_port_t handler_thread)
: exception_type_(0),
exception_code_(0),
exception_thread_(0),
@@ -71,7 +75,7 @@
} else {
dynamic_images_ = NULL;
}
-
+
GatherSystemInformation();
}
@@ -89,26 +93,29 @@
// If this is non-zero, then we've already gathered the information
if (os_major_version_)
return;
-
+
// This code extracts the version and build information from the OS
CFStringRef vers_path =
CFSTR("/System/Library/CoreServices/SystemVersion.plist");
CFURLRef sys_vers =
- CFURLCreateWithFileSystemPath(NULL, vers_path, kCFURLPOSIXPathStyle, false);
+ CFURLCreateWithFileSystemPath(NULL,
+ vers_path,
+ kCFURLPOSIXPathStyle,
+ false);
CFDataRef data;
SInt32 error;
CFURLCreateDataAndPropertiesFromResource(NULL, sys_vers, &data, NULL, NULL,
&error);
-
+
if (!data)
return;
-
+
CFDictionaryRef list = static_cast<CFDictionaryRef>
(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable,
NULL));
if (!list)
return;
-
+
CFStringRef build_version = static_cast<CFStringRef>
(CFDictionaryGetValue(list, CFSTR("ProductBuildVersion")));
CFStringRef product_version = static_cast<CFStringRef>
@@ -203,39 +210,48 @@
dir.CopyIndex(i, &local_dir);
}
}
-
return result;
}
-size_t MinidumpGenerator::CalculateStackSize(vm_address_t start_addr) {
- vm_address_t stack_region_base = start_addr;
- vm_size_t stack_region_size;
+size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) {
+ mach_vm_address_t stack_region_base = start_addr;
+ mach_vm_size_t stack_region_size;
natural_t nesting_level = 0;
- vm_region_submap_info submap_info;
- mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT;
- kern_return_t result =
- vm_region_recurse(crashing_task_, &stack_region_base, &stack_region_size,
- &nesting_level,
- reinterpret_cast<vm_region_recurse_info_t>(&submap_info),
- &info_count);
-
- if ((stack_region_base + stack_region_size) == 0xbffff000) {
- // The stack for thread 0 needs to extend all the way to 0xc0000000
- // For many processes the stack is first created in one page
- // from 0xbffff000 - 0xc0000000 and is then later extended to
- // a much larger size by creating a new VM region immediately below
- // the initial page
+ vm_region_submap_info_64 submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+ vm_region_recurse_info_t region_info;
+ region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info);
- // include the original stack frame page (0xbffff000 - 0xc0000000)
- stack_region_size += 0x1000;
+ kern_return_t result =
+ mach_vm_region_recurse(crashing_task_, &stack_region_base,
+ &stack_region_size, &nesting_level,
+ region_info,
+ &info_count);
+
+ if ((stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK) {
+ // The stack for thread 0 needs to extend all the way to
+ // 0xc0000000 on 32 bit and 00007fff5fc00000 on 64bit. HOWEVER,
+ // for many processes, the stack is first created in one page
+ // below this, and is then later extended to a much larger size by
+ // creating a new VM region immediately below the initial page.
+
+ // You can see this for yourself by running vmmap on a "hello,
+ // world" program
+
+ // Because of the above, we'll add 4k to include the original
+ // stack frame page.
+ // This method of finding the stack region needs to be done in
+ // a better way; the breakpad issue 247 is tracking this.
+ stack_region_size += 0x1000;
}
- return result == KERN_SUCCESS ?
+ return result == KERN_SUCCESS ?
stack_region_base + stack_region_size - start_addr : 0;
}
bool MinidumpGenerator::WriteStackFromStartAddress(
- vm_address_t start_addr,
+ mach_vm_address_t start_addr,
MDMemoryDescriptor *stack_location) {
UntypedMDRVA memory(&writer_);
size_t size = CalculateStackSize(start_addr);
@@ -250,55 +266,80 @@
bool result;
if (dynamic_images_) {
- void *stack_memory = ReadTaskMemory(crashing_task_, (void*)start_addr, size);
+
+ kern_return_t kr;
+
+ void *stack_memory = ReadTaskMemory(crashing_task_,
+ (void*)start_addr,
+ size,
+ &kr);
+
+ if (stack_memory == NULL) {
+ return false;
+ }
+
result = memory.Copy(stack_memory, size);
free(stack_memory);
} else {
result = memory.Copy(reinterpret_cast<const void *>(start_addr), size);
}
-
+
stack_location->start_of_memory_range = start_addr;
stack_location->memory = memory.location();
return result;
}
-#if TARGET_CPU_PPC
+#if TARGET_CPU_PPC || TARGET_CPU_PPC64
bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
MDMemoryDescriptor *stack_location) {
- ppc_thread_state_t *machine_state =
- reinterpret_cast<ppc_thread_state_t *>(state);
- vm_address_t start_addr = machine_state->r1;
+ breakpad_thread_state_t *machine_state =
+ reinterpret_cast<breakpad_thread_state_t *>(state);
+#if TARGET_CPU_PPC
+ mach_vm_address_t start_addr = machine_state->r1;
+#else
+ mach_vm_address_t start_addr = machine_state->__r1;
+#endif
return WriteStackFromStartAddress(start_addr, stack_location);
}
-u_int64_t MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
- ppc_thread_state_t *machine_state =
- reinterpret_cast<ppc_thread_state_t *>(state);
+u_int64_t
+MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
+ breakpad_thread_state_t *machine_state =
+ reinterpret_cast<breakpad_thread_state_t *>(state);
+#if TARGET_CPU_PPC
return machine_state->srr0;
+#else
+ return machine_state->__srr0;
+#endif
}
bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
MDLocationDescriptor *register_location) {
- TypedMDRVA<MDRawContextPPC> context(&writer_);
- ppc_thread_state_t *machine_state =
- reinterpret_cast<ppc_thread_state_t *>(state);
+ TypedMDRVA<MinidumpContext> context(&writer_);
+ breakpad_thread_state_t *machine_state =
+ reinterpret_cast<breakpad_thread_state_t *>(state);
if (!context.Allocate())
return false;
*register_location = context.location();
- MDRawContextPPC *context_ptr = context.get();
+ MinidumpContext *context_ptr = context.get();
context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
+#if TARGET_CPU_PPC64
+#define AddReg(a) context_ptr->a = machine_state->__ ## a
+#define AddGPR(a) context_ptr->gpr[a] = machine_state->__r ## a
+#else
#define AddReg(a) context_ptr->a = machine_state->a
#define AddGPR(a) context_ptr->gpr[a] = machine_state->r ## a
+#endif
+
AddReg(srr0);
AddReg(cr);
AddReg(xer);
AddReg(ctr);
- AddReg(mq);
AddReg(lr);
AddReg(vrsave);
@@ -334,38 +375,68 @@
AddGPR(29);
AddGPR(30);
AddGPR(31);
+
+#if TARGET_CPU_PPC
+ /* The mq register is only for PPC */
+ AddReg(mq);
+#endif
+
+
return true;
}
-#elif TARGET_CPU_X86
+#elif TARGET_CPU_X86 || TARGET_CPU_X86_64
+
bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
MDMemoryDescriptor *stack_location) {
- i386_thread_state_t *machine_state =
- reinterpret_cast<i386_thread_state_t *>(state);
- vm_address_t start_addr = machine_state->esp;
+ breakpad_thread_state_t *machine_state =
+ reinterpret_cast<breakpad_thread_state_t *>(state);
+
+#if TARGET_CPU_X86_64
+ mach_vm_address_t start_addr = machine_state->__rsp;
+#else
+ mach_vm_address_t start_addr = machine_state->esp;
+#endif
return WriteStackFromStartAddress(start_addr, stack_location);
}
-u_int64_t MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
- i386_thread_state_t *machine_state =
- reinterpret_cast<i386_thread_state_t *>(state);
-
+u_int64_t
+MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
+ breakpad_thread_state_t *machine_state =
+ reinterpret_cast<breakpad_thread_state_t *>(state);
+
+#if TARGET_CPU_X86_64
+ return machine_state->__rip;
+#else
return machine_state->eip;
+#endif
}
bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
MDLocationDescriptor *register_location) {
- TypedMDRVA<MDRawContextX86> context(&writer_);
- i386_thread_state_t *machine_state =
- reinterpret_cast<i386_thread_state_t *>(state);
+ TypedMDRVA<MinidumpContext> context(&writer_);
+ breakpad_thread_state_t *machine_state =
+ reinterpret_cast<breakpad_thread_state_t *>(state);
if (!context.Allocate())
return false;
*register_location = context.location();
- MDRawContextX86 *context_ptr = context.get();
+ MinidumpContext *context_ptr = context.get();
+
+#if TARGET_CPU_X86
context_ptr->context_flags = MD_CONTEXT_X86;
+
#define AddReg(a) context_ptr->a = machine_state->a
+ AddReg(eax);
+ AddReg(ebx);
+ AddReg(ecx);
+ AddReg(edx);
+ AddReg(esi);
+ AddReg(edi);
+ AddReg(ebp);
+ AddReg(esp);
+
AddReg(cs);
AddReg(ds);
AddReg(ss);
@@ -375,14 +446,37 @@
AddReg(eflags);
AddReg(eip);
- AddReg(eax);
- AddReg(ebx);
- AddReg(ecx);
- AddReg(edx);
- AddReg(esi);
- AddReg(edi);
- AddReg(ebp);
- AddReg(esp);
+#else
+
+#define AddReg(a) context_ptr->a = machine_state->__ ## a
+ context_ptr->context_flags = MD_CONTEXT_AMD64;
+ AddReg(rax);
+ AddReg(rbx);
+ AddReg(rcx);
+ AddReg(rdx);
+ AddReg(rdi);
+ AddReg(rsi);
+ AddReg(rbp);
+ AddReg(rsp);
+ AddReg(r8);
+ AddReg(r9);
+ AddReg(r10);
+ AddReg(r11);
+ AddReg(r12);
+ AddReg(r13);
+ AddReg(r14);
+ AddReg(r15);
+ AddReg(rip);
+ // according to AMD's software developer guide, bits above 18 are
+ // not used in the flags register. Since the minidump format
+ // specifies 32 bits for the flags register, we can truncate safely
+ // with no loss.
+ context_ptr->eflags = machine_state->__rflags;
+ AddReg(cs);
+ AddReg(fs);
+ AddReg(gs);
+#endif
+
return true;
}
#endif
@@ -447,7 +541,8 @@
return true;
}
-bool MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
+bool
+MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
TypedMDRVA<MDRawExceptionStream> exception(&writer_);
if (!exception.Allocate())
@@ -466,7 +561,9 @@
breakpad_thread_state_data_t state;
mach_msg_type_number_t stateCount = sizeof(state);
- if (thread_get_state(exception_thread_, BREAKPAD_MACHINE_THREAD_STATE, state,
+ if (thread_get_state(exception_thread_,
+ BREAKPAD_MACHINE_THREAD_STATE,
+ state,
&stateCount) != KERN_SUCCESS)
return false;
@@ -508,13 +605,13 @@
// to preserve it.
#define cpuid(op,eax,ebx,ecx,edx) \
asm ("pushl %%ebx \n\t" \
- "cpuid \n\t" \
- "movl %%ebx,%1 \n\t" \
- "popl %%ebx" \
- : "=a" (eax), \
- "=g" (ebx), \
- "=c" (ecx), \
- "=d" (edx) \
+ "cpuid \n\t" \
+ "movl %%ebx,%1 \n\t" \
+ "popl %%ebx" \
+ : "=a" (eax), \
+ "=g" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
: "0" (op))
int unused, unused2;
// get vendor id
@@ -564,7 +661,7 @@
if (!image)
return false;
- const mach_header *header = image->GetMachHeader();
+ const breakpad_mach_header *header = image->GetMachHeader();
if (!header)
return false;
@@ -588,11 +685,24 @@
}
} else {
// we're getting module info in the crashed process
- const struct mach_header *header = _dyld_get_image_header(index);
+ const breakpad_mach_header *header;
+ header = (breakpad_mach_header*)_dyld_get_image_header(index);
if (!header)
return false;
+#ifdef __LP64__
+ assert(header->magic == MH_MAGIC_64);
+
+ if(header->magic != MH_MAGIC_64)
+ return false;
+#else
+ assert(header->magic == MH_MAGIC);
+
+ if(header->magic != MH_MAGIC)
+ return false;
+#endif
+
int cpu_type = header->cputype;
unsigned long slide = _dyld_get_image_vmaddr_slide(index);
const char* name = _dyld_get_image_name(index);
@@ -603,8 +713,10 @@
for (unsigned int i = 0; cmd && (i < header->ncmds); i++) {
if (cmd->cmd == LC_SEGMENT) {
- const struct segment_command *seg =
- reinterpret_cast<const struct segment_command *>(cmd);
+
+ const breakpad_mach_segment_command *seg =
+ reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
+
if (!strcmp(seg->segname, "__TEXT")) {
MDLocationDescriptor string_location;
@@ -622,10 +734,10 @@
}
}
- cmd = reinterpret_cast<struct load_command *>((char *)cmd + cmd->cmdsize);
+ cmd = reinterpret_cast<struct load_command*>((char *)cmd + cmd->cmdsize);
}
}
-
+
return true;
}
@@ -647,7 +759,7 @@
return index;
}
}
-
+
// failed - just use the first image
return 0;
}
@@ -681,9 +793,9 @@
// Get the module identifier
FileID file_id(module_path);
unsigned char identifier[16];
-
+
if (file_id.MachoIdentifier(cpu_type, identifier)) {
- cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 |
+ cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 |
(uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 |
(uint32_t)identifier[3];
cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5];
@@ -705,9 +817,6 @@
MDRawDirectory *module_list_stream) {
TypedMDRVA<MDRawModuleList> list(&writer_);
- if (!_dyld_present())
- return false;
-
int image_count = dynamic_images_ ?
dynamic_images_->GetImageCount() : _dyld_image_count();
@@ -770,12 +879,15 @@
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, info_ptr->process_id };
size_t size;
if (!sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &size, NULL, 0)) {
- vm_address_t addr;
- if (vm_allocate(mach_task_self(), &addr, size, true) == KERN_SUCCESS) {
+ mach_vm_address_t addr;
+ if (mach_vm_allocate(mach_task_self(),
+ &addr,
+ size,
+ true) == KERN_SUCCESS) {
struct kinfo_proc *proc = (struct kinfo_proc *)addr;
if (!sysctl(mib, sizeof(mib) / sizeof(mib[0]), proc, &size, NULL, 0))
info_ptr->process_create_time = proc->kp_proc.p_starttime.tv_sec;
- vm_deallocate(mach_task_self(), addr, size);
+ mach_vm_deallocate(mach_task_self(), addr, size);
}
}
Modified: trunk/google-breakpad/src/client/mac/handler/minidump_generator.h
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/minidump_generator.h (original)
+++ trunk/google-breakpad/src/client/mac/handler/minidump_generator.h Sun Oct 19 13:26:38 2008
@@ -46,6 +46,26 @@
using std::string;
+#if TARGET_CPU_X86_64 || TARGET_CPU_PPC64
+#define TOP_OF_THREAD0_STACK 0x00007fff5fbff000
+#else
+#define TOP_OF_THREAD0_STACK 0xbffff000
+#endif
+
+#if TARGET_CPU_X86_64
+typedef x86_thread_state64_t breakpad_thread_state_t;
+typedef MDRawContextAMD64 MinidumpContext;
+#elif TARGET_CPU_X86
+typedef i386_thread_state_t breakpad_thread_state_t;
+typedef MDRawContextX86 MinidumpContext;
+#elif TARGET_CPU_PPC64
+typedef ppc_thread_state64_t breakpad_thread_state_t;
+typedef MDRawContextPPC64 MinidumpContext;
+#elif TARGET_CPU_PPC
+typedef ppc_thread_state_t breakpad_thread_state_t;
+typedef MDRawContextPPC MinidumpContext;
+#endif
+
// Creates a minidump file of the current process. If there is exception data,
// use SetExceptionInformation() to add this to the minidump. The minidump
// file is generated by the Write() function.
@@ -93,7 +113,7 @@
// Helpers
u_int64_t CurrentPCForStack(breakpad_thread_state_data_t state);
- bool WriteStackFromStartAddress(vm_address_t start_addr,
+ bool WriteStackFromStartAddress(mach_vm_address_t start_addr,
MDMemoryDescriptor *stack_location);
bool WriteStack(breakpad_thread_state_data_t state,
MDMemoryDescriptor *stack_location);
@@ -103,7 +123,9 @@
bool WriteCVRecord(MDRawModule *module, int cpu_type,
const char *module_path);
bool WriteModuleStream(unsigned int index, MDRawModule *module);
- size_t CalculateStackSize(vm_address_t start_addr);
+
+ size_t CalculateStackSize(mach_vm_address_t start_addr);
+
int FindExecutableModule();
// disallow copy ctor and operator=
Modified: trunk/google-breakpad/src/client/mac/handler/minidump_generator_test.cc
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/minidump_generator_test.cc (original)
+++ trunk/google-breakpad/src/client/mac/handler/minidump_generator_test.cc Sun Oct 19 13:26:38 2008
@@ -48,9 +48,13 @@
struct passwd *user = getpwuid(getuid());
// Write it to the desktop
- snprintf(buffer, sizeof(buffer), "/Users/%s/Desktop/test.dmp", user->pw_name);
+ snprintf(buffer,
+ sizeof(buffer),
+ "/Users/%s/Desktop/test.dmp",
+ user->pw_name);
+
fprintf(stdout, "Writing %s\n", buffer);
-
+ unlink(buffer);
md.Write(buffer);
doneWritingReport = true;
Modified: trunk/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj
==============================================================================
--- trunk/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj (original)
+++ trunk/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj Sun Oct 19 13:26:38 2008
@@ -49,6 +49,24 @@
D2F6511E0BEF973600920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
D2F651210BEF975400920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9721F310E8B07E800D7E813 /* dwarftests.mm */; };
+ F93A88870E8B4C9A0026AF89 /* dump_syms.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9721F390E8B0D0D00D7E813 /* dump_syms.mm */; };
+ F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F760E8B0DC700D7E813 /* bytereader.cc */; };
+ F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */; };
+ F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F780E8B0DC700D7E813 /* functioninfo.cc */; };
+ F93A888B0E8B4C9A0026AF89 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = F9721FA80E8B0E4800D7E813 /* md5.c */; };
+ F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */; };
+ F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */; };
+ F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */; };
+ F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ F9AE5B390DBFDBDB00505983 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ F9AE5B3A0DBFDBDB00505983 /* DynamicImagesTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */; };
+ F9B34E870DBC1E1600306484 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ F9C5A4220DB82DD800209C76 /* DynamicImagesTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -106,6 +124,30 @@
D2F651080BEF949A00920385 /* dynamic_images.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dynamic_images.h; sourceTree = "<group>"; };
D2F6510C0BEF94EB00920385 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
D2F6510D0BEF94EB00920385 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ F917C4F70E03265A00F86017 /* breakpad_exc_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = breakpad_exc_server.c; sourceTree = "<group>"; };
+ F917C4F80E03265A00F86017 /* breakpad_exc_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_exc_server.h; sourceTree = "<group>"; };
+ F93A88750E8B4C700026AF89 /* octestcases.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = octestcases.octest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "obj-cTestCases-Info.plist"; sourceTree = "<group>"; };
+ F9721F300E8B07E800D7E813 /* dwarftests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dwarftests.h; sourceTree = "<group>"; };
+ F9721F310E8B07E800D7E813 /* dwarftests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dwarftests.mm; sourceTree = "<group>"; };
+ F9721F380E8B0CFC00D7E813 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
+ F9721F390E8B0D0D00D7E813 /* dump_syms.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.mm; path = ../../../common/mac/dump_syms.mm; sourceTree = SOURCE_ROOT; };
+ F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
+ F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = /System/Library/Frameworks/SenTestingKit.framework; sourceTree = "<absolute>"; };
+ F9721FA80E8B0E4800D7E813 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../../../common/md5.c; sourceTree = SOURCE_ROOT; };
+ F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = "<group>"; };
+ F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_test.cc; sourceTree = "<group>"; };
+ F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_64.cc; sourceTree = "<group>"; };
+ F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_64.h; sourceTree = "<group>"; };
+ F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests32-Info.plist"; sourceTree = "<group>"; };
+ F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests64.cptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests32.cptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9AE5B340DBFDBA300505983 /* minidump_tests64-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests64-Info.plist"; sourceTree = "<group>"; };
+ F9C5A4200DB82DD800209C76 /* DynamicImagesTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicImagesTests.h; sourceTree = "<group>"; };
+ F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicImagesTests.cc; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -132,12 +174,45 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ F93A88720E8B4C700026AF89 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19C00DB04A9500C98454 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B300DBFDBA300505983 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */,
+ F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* MinidumpWriter */ = {
isa = PBXGroup;
children = (
+ F9721FA80E8B0E4800D7E813 /* md5.c */,
+ F9721F760E8B0DC700D7E813 /* bytereader.cc */,
+ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */,
+ F9721F780E8B0DC700D7E813 /* functioninfo.cc */,
+ F9721F390E8B0D0D00D7E813 /* dump_syms.mm */,
+ F9721F380E8B0CFC00D7E813 /* dump_syms.h */,
+ F917C4F70E03265A00F86017 /* breakpad_exc_server.c */,
+ F917C4F80E03265A00F86017 /* breakpad_exc_server.h */,
+ F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */,
+ F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */,
D2F6510C0BEF94EB00920385 /* macho_walker.cc */,
D2F6510D0BEF94EB00920385 /* macho_walker.h */,
D2F651070BEF949A00920385 /* dynamic_images.cc */,
@@ -148,10 +223,14 @@
D2F650FD0BEF947200920385 /* macho_id.h */,
D2F650FE0BEF947200920385 /* macho_utilities.cc */,
D2F650FF0BEF947200920385 /* macho_utilities.h */,
+ F9C5A41F0DB82DB000209C76 /* testcases */,
9BD82C040B0133420055103E /* Breakpad */,
08FB7795FE84155DC02AAC07 /* Source */,
9B37CEEA0AF98EB600FA4BD4 /* Frameworks */,
1AB674ADFE9D54B511CA2CBB /* Products */,
+ F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */,
+ F9AE5B340DBFDBA300505983 /* minidump_tests64-Info.plist */,
+ F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */,
);
name = MinidumpWriter;
sourceTree = "<group>";
@@ -172,6 +251,9 @@
8DD76F6C0486A84900D96B5E /* generator_test */,
9BD82A9B0B00267E0055103E /* handler_test */,
9B7CA84E0B1297F200CD3A1D /* unit_test */,
+ F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */,
+ F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */,
+ F93A88750E8B4C700026AF89 /* octestcases.octest */,
);
name = Products;
sourceTree = "<group>";
@@ -179,6 +261,8 @@
9B37CEEA0AF98EB600FA4BD4 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */,
+ F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */,
9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */,
);
name = Frameworks;
@@ -204,6 +288,19 @@
name = Breakpad;
sourceTree = "<group>";
};
+ F9C5A41F0DB82DB000209C76 /* testcases */ = {
+ isa = PBXGroup;
+ children = (
+ F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */,
+ F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */,
+ F9C5A4200DB82DD800209C76 /* DynamicImagesTests.h */,
+ F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */,
+ F9721F300E8B07E800D7E813 /* dwarftests.h */,
+ F9721F310E8B07E800D7E813 /* dwarftests.mm */,
+ );
+ path = testcases;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -257,23 +354,148 @@
productReference = 9BD82A9B0B00267E0055103E /* handler_test */;
productType = "com.apple.product-type.tool";
};
+ F93A88740E8B4C700026AF89 /* obj-c_TestCases */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F93A88790E8B4C700026AF89 /* Build configuration list for PBXNativeTarget "obj-c_TestCases" */;
+ buildPhases = (
+ F93A88700E8B4C700026AF89 /* Resources */,
+ F93A88710E8B4C700026AF89 /* Sources */,
+ F93A88720E8B4C700026AF89 /* Frameworks */,
+ F93A88730E8B4C700026AF89 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "obj-c_TestCases";
+ productName = octestcases;
+ productReference = F93A88750E8B4C700026AF89 /* octestcases.octest */;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9AE19C20DB04A9500C98454 /* minidump_tests64 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests64" */;
+ buildPhases = (
+ F9AE19BE0DB04A9500C98454 /* Resources */,
+ F9AE19BF0DB04A9500C98454 /* Sources */,
+ F9AE19C00DB04A9500C98454 /* Frameworks */,
+ F9AE19C10DB04A9500C98454 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_tests64;
+ productName = minidump_tests;
+ productReference = F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9AE5B320DBFDBA300505983 /* minidump_tests32 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F9AE5B380DBFDBA300505983 /* Build configuration list for PBXNativeTarget "minidump_tests32" */;
+ buildPhases = (
+ F9AE5B2E0DBFDBA300505983 /* Resources */,
+ F9AE5B2F0DBFDBA300505983 /* Sources */,
+ F9AE5B300DBFDBA300505983 /* Frameworks */,
+ F9AE5B310DBFDBA300505983 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_tests32;
+ productName = Untitled;
+ productReference = F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */;
+ productType = "com.apple.product-type.bundle";
+ };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* MinidumpWriter */;
projectDirPath = "";
+ projectRoot = "";
targets = (
8DD76F620486A84900D96B5E /* generator_test */,
9BD82A9A0B00267E0055103E /* handler_test */,
9B7CA84D0B1297F200CD3A1D /* unit_test */,
+ F9AE19C20DB04A9500C98454 /* minidump_tests64 */,
+ F9AE5B320DBFDBA300505983 /* minidump_tests32 */,
+ F93A88740E8B4C700026AF89 /* obj-c_TestCases */,
);
};
/* End PBXProject section */
+/* Begin PBXResourcesBuildPhase section */
+ F93A88700E8B4C700026AF89 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19BE0DB04A9500C98454 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B2E0DBFDBA300505983 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F93A88730E8B4C700026AF89 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
+ };
+ F9AE19C10DB04A9500C98454 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n# Run gcov on the framework getting tested\nif [ \"${CONFIGURATION}\" = 'Coverage' ];\nthen\n FRAMEWORK_NAME=minidump_tests64\n FRAMEWORK_OBJ_DIR=${OBJROOT}/${PROJECT_NAME}.build/${CONFIGURATION}/${FRAMEWORK_NAME}.build/Objects-normal/${NATIVE_ARCH_ACTUAL}\n mkdir -p coverage\n pushd coverage\n echo find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n popd\nfi ";
+ };
+ F9AE5B310DBFDBA300505983 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
/* Begin PBXSourcesBuildPhase section */
8DD76F640486A84900D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
@@ -324,6 +546,43 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ F93A88710E8B4C700026AF89 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */,
+ F93A88870E8B4C9A0026AF89 /* dump_syms.mm in Sources */,
+ F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */,
+ F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */,
+ F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */,
+ F93A888B0E8B4C9A0026AF89 /* md5.c in Sources */,
+ F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */,
+ F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */,
+ F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */,
+ F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19BF0DB04A9500C98454 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9B34E870DBC1E1600306484 /* dynamic_images.cc in Sources */,
+ F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */,
+ F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */,
+ F9C5A4220DB82DD800209C76 /* DynamicImagesTests.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B2F0DBFDBA300505983 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9AE5B390DBFDBDB00505983 /* dynamic_images.cc in Sources */,
+ F9AE5B3A0DBFDBDB00505983 /* DynamicImagesTests.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
@@ -456,6 +715,182 @@
};
name = Release;
};
+ F93A88770E8B4C700026AF89 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ GCC_CHAR_IS_UNSIGNED_CHAR = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INFOPLIST_FILE = "obj-cTestCases-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
+ OTHER_LDFLAGS = (
+ "-lcrypto",
+ "-framework",
+ Cocoa,
+ "-framework",
+ SenTestingKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = octestcases;
+ USER_HEADER_SEARCH_PATHS = "../../../..//**";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Debug;
+ };
+ F93A88780E8B4C700026AF89 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ GCC_CHAR_IS_UNSIGNED_CHAR = YES;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_MODEL_TUNING = G5;
+ INFOPLIST_FILE = "obj-cTestCases-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
+ OTHER_LDFLAGS = (
+ "-lcrypto",
+ "-framework",
+ Cocoa,
+ "-framework",
+ SenTestingKit,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = octestcases;
+ USER_HEADER_SEARCH_PATHS = "../../../..//**";
+ WRAPPER_EXTENSION = octest;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ F9AE19C40DB04A9500C98454 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ ppc64,
+ );
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+ INFOPLIST_FILE = "minidump_tests64-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ OTHER_LDFLAGS = (
+ "-framework",
+ Carbon,
+ "-framework",
+ CPlusTest,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = minidump_tests64;
+ SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Debug;
+ };
+ F9AE19C50DB04A9500C98454 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = (
+ "$(NATIVE_ARCH_64_BIT)",
+ ppc64,
+ );
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+ INFOPLIST_FILE = "minidump_tests64-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ OTHER_LDFLAGS = (
+ "-framework",
+ Carbon,
+ "-framework",
+ CPlusTest,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = minidump_tests64;
+ SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ F9AE5B350DBFDBA300505983 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH)";
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+ INFOPLIST_FILE = "minidump_tests32-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
+ OTHER_LDFLAGS = (
+ "-framework",
+ Carbon,
+ "-framework",
+ CPlusTest,
+ "-lcrypto",
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = minidump_tests32;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Debug;
+ };
+ F9AE5B370DBFDBA300505983 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH)";
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+ INFOPLIST_FILE = "minidump_tests32-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
+ OTHER_LDFLAGS = (
+ "-lcrypto",
+ "-framework",
+ Carbon,
+ "-framework",
+ CPlusTest,
+ );
+ PREBINDING = NO;
+ PRODUCT_NAME = minidump_tests32;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -495,6 +930,33 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ F93A88790E8B4C700026AF89 /* Build configuration list for PBXNativeTarget "obj-c_TestCases" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F93A88770E8B4C700026AF89 /* Debug */,
+ F93A88780E8B4C700026AF89 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests64" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F9AE19C40DB04A9500C98454 /* Debug */,
+ F9AE19C50DB04A9500C98454 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F9AE5B380DBFDBA300505983 /* Build configuration list for PBXNativeTarget "minidump_tests32" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F9AE5B350DBFDBA300505983 /* Debug */,
+ F9AE5B370DBFDBA300505983 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
Modified: trunk/google-breakpad/src/client/minidump_file_writer_unittest.cc
==============================================================================
--- trunk/google-breakpad/src/client/minidump_file_writer_unittest.cc (original)
+++ trunk/google-breakpad/src/client/minidump_file_writer_unittest.cc Sun Oct 19 13:26:38 2008
@@ -145,6 +145,18 @@
ASSERT_NE(fd, -1);
ASSERT_TRUE(buffer);
ASSERT_EQ(read(fd, buffer, expected_byte_count), expected_byte_count);
+
+ char *b1, *b2;
+ b1 = (char*)buffer;
+ b2 = (char*)expected;
+ while (*b1 == *b2) {
+ b1++;
+ b2++;
+ }
+
+ printf("%d\n",b1 - (char*)buffer);
+
+
ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0);
return true;
}
Modified: trunk/google-breakpad/src/client/solaris/handler/Makefile
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/Makefile (original)
+++ trunk/google-breakpad/src/client/solaris/handler/Makefile Sun Oct 19 13:26:38 2008
@@ -40,6 +40,7 @@
THREAD_SRC=solaris_lwp.cc
SHARE_SRC=../../minidump_file_writer.cc\
+ ../../../common/md5.c\
../../../common/string_conversion.cc\
../../../common/solaris/file_id.cc\
minidump_generator.cc
Modified: trunk/google-breakpad/src/client/solaris/handler/exception_handler.cc
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/exception_handler.cc (original)
+++ trunk/google-breakpad/src/client/solaris/handler/exception_handler.cc Sun Oct 19 13:26:38 2008
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
}
}
-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 @@
// 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 @@
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 @@
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)
Modified: trunk/google-breakpad/src/client/solaris/handler/exception_handler.h
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/exception_handler.h (original)
+++ trunk/google-breakpad/src/client/solaris/handler/exception_handler.h Sun Oct 19 13:26:38 2008
@@ -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 @@
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 @@
// 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_;
Modified: trunk/google-breakpad/src/client/solaris/handler/minidump_generator.cc
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/minidump_generator.cc (original)
+++ trunk/google-breakpad/src/client/solaris/handler/minidump_generator.cc Sun Oct 19 13:26:38 2008
@@ -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 @@
}
#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 @@
}
#endif /* TARGET_CPU_XXX */
-bool MinidumpGenerator::WriteLwpStream(lwpstatus_t *lsp, MDRawThread *lwp) {
+// 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
+ 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;
- prgregset_t *gregs = &(lsp->pr_reg);
- UntypedMDRVA memory(&writer_);
+ const prgregset_t *gregs = &(lsp->pr_reg);
+ UntypedMDRVA memory(minidump_writer);
#if TARGET_CPU_SPARC
- if (!WriteLwpStack((*gregs)[R_SP],
+ 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 @@
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
}
struct ModuleInfoCallbackCtx {
- MinidumpGenerator *generator;
MinidumpFileWriter *minidump_writer;
+ const WriterArgument *writer_args;
TypedMDRVA<MDRawModuleList> *list;
int module_index;
};
@@ -338,16 +505,29 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
SolarisLwp *lwp_;
};
+// Prototype of writer functions.
+typedef bool (*WriteStreamFN)(MinidumpFileWriter *,
+ const WriterArgument *,
+ MDRawDirectory *);
+
+// 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() {
- // Function table to writer a full minidump.
- const WriteStreamFN writers[] = {
- &MinidumpGenerator::WriteLwpListStream,
- &MinidumpGenerator::WriteModuleListStream,
- &MinidumpGenerator::WriteSystemInfoStream,
- &MinidumpGenerator::WriteExceptionStream,
- &MinidumpGenerator::WriteMiscInfoStream,
- &MinidumpGenerator::WriteBreakpadInfoStream,
- };
+//void* MinidumpGenerator::Write(void *argument) {
+void* Write(void *argument) {
+ WriterArgument *writer_args = static_cast<WriterArgument *>(argument);
- if (!lwp_lister_->ControlAllLwps(true))
+ 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,30 +731,53 @@
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);
- assert(stack_ != 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;
Modified: trunk/google-breakpad/src/client/solaris/handler/minidump_generator.h
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/minidump_generator.h (original)
+++ trunk/google-breakpad/src/client/solaris/handler/minidump_generator.h Sun Oct 19 13:26:38 2008
@@ -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 @@
// 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
Modified: trunk/google-breakpad/src/client/solaris/handler/minidump_test.cc
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/minidump_test.cc (original)
+++ trunk/google-breakpad/src/client/solaris/handler/minidump_test.cc Sun Oct 19 13:26:38 2008
@@ -48,7 +48,7 @@
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;
Modified: trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.cc
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.cc (original)
+++ trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.cc Sun Oct 19 13:26:38 2008
@@ -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 @@
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 @@
}
// 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 @@
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 @@
}
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 @@
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;
}
@@ -655,4 +713,53 @@
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
Modified: trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.h
==============================================================================
--- trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.h (original)
+++ trunk/google-breakpad/src/client/solaris/handler/solaris_lwp.h Sun Oct 19 13:26:38 2008
@@ -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 @@
// 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_;
Modified: trunk/google-breakpad/src/client/windows/breakpad_client.sln
==============================================================================
--- trunk/google-breakpad/src/client/windows/breakpad_client.sln (original)
+++ trunk/google-breakpad/src/client/windows/breakpad_client.sln Sun Oct 19 13:26:38 2008
@@ -1,36 +1,49 @@
-ï
-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}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_report_sender", "sender\crash_report_sender.vcproj", "{9946A048-043B-4F8F-9E07-9297B204714C}"
-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
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Debug|Win32.ActiveCfg = Debug|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Debug|Win32.Build.0 = Debug|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Release|Win32.ActiveCfg = Release|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Release|Win32.Build.0 = Release|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32
- {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32
- {9946A048-043B-4F8F-9E07-9297B204714C}.Debug|Win32.ActiveCfg = Debug|Win32
- {9946A048-043B-4F8F-9E07-9297B204714C}.Debug|Win32.Build.0 = Debug|Win32
- {9946A048-043B-4F8F-9E07-9297B204714C}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32
- {9946A048-043B-4F8F-9E07-9297B204714C}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32
- {9946A048-043B-4F8F-9E07-9297B204714C}.Release|Win32.ActiveCfg = Release|Win32
- {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
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+ï
+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
+ DebugStaticCRT|Win32 = DebugStaticCRT|Win32
+ Release|Win32 = Release|Win32
+ ReleaseStaticCRT|Win32 = ReleaseStaticCRT|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Debug|Win32.Build.0 = Debug|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Release|Win32.ActiveCfg = Release|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.Release|Win32.Build.0 = Release|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32
+ {B55CA863-B374-4BAF-95AC-539E4FA4C90C}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32
+ {9946A048-043B-4F8F-9E07-9297B204714C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9946A048-043B-4F8F-9E07-9297B204714C}.Debug|Win32.Build.0 = Debug|Win32
+ {9946A048-043B-4F8F-9E07-9297B204714C}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32
+ {9946A048-043B-4F8F-9E07-9297B204714C}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32
+ {9946A048-043B-4F8F-9E07-9297B204714C}.Release|Win32.ActiveCfg = Release|Win32
+ {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
+ EndGlobalSection
+EndGlobal
Added: trunk/google-breakpad/src/client/windows/common/auto_critical_section.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/common/auto_critical_section.h Sun Oct 19 13:26:38 2008
@@ -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__
Added: trunk/google-breakpad/src/client/windows/common/ipc_protocol.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/common/ipc_protocol.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,179 @@
+// 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 <string>
+#include <utility>
+#include "common/windows/string_utils-inl.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Name/value pair for custom client information.
+struct CustomInfoEntry {
+ // Maximum length for name and value for client custom info.
+ static const int kNameMaxLength = 64;
+ static const int kValueMaxLength = 64;
+
+ CustomInfoEntry() {
+ // Putting name and value in initializer list makes VC++ show warning 4351.
+ set_name(NULL);
+ set_value(NULL);
+ }
+
+ CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) {
+ set_name(name_arg);
+ set_value(value_arg);
+ }
+
+ void set_name(const wchar_t* name_arg) {
+ if (!name_arg) {
+ name[0] = L'\0';
+ return;
+ }
+ WindowsStringUtils::safe_wcscpy(name, kNameMaxLength, name_arg);
+ }
+
+ void set_value(const wchar_t* value_arg) {
+ if (!value_arg) {
+ value[0] = L'\0';
+ return;
+ }
+
+ WindowsStringUtils::safe_wcscpy(value, kValueMaxLength, value_arg);
+ }
+
+ void set(const wchar_t* name_arg, const wchar_t* value_arg) {
+ set_name(name_arg);
+ set_value(value_arg);
+ }
+
+ wchar_t name[kNameMaxLength];
+ wchar_t value[kValueMaxLength];
+};
+
+// 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
+};
+
+struct CustomClientInfo {
+ const CustomInfoEntry* entries;
+ int count;
+};
+
+// 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),
+ custom_client_info(),
+ 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,
+ const CustomClientInfo& custom_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),
+ custom_client_info(custom_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;
+
+ // Custom client information.
+ CustomClientInfo custom_client_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__
Added: trunk/google-breakpad/src/client/windows/crash_generation/ReadMe.txt
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/ReadMe.txt Sun Oct 19 13:26:38 2008
@@ -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.
+=========================================================================
Added: trunk/google-breakpad/src/client/windows/crash_generation/client_info.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/client_info.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,210 @@
+// 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"
+#include "client/windows/common/ipc_protocol.h"
+
+static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime";
+
+namespace google_breakpad {
+
+ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
+ DWORD pid,
+ MINIDUMP_TYPE dump_type,
+ DWORD* thread_id,
+ EXCEPTION_POINTERS** ex_info,
+ MDRawAssertionInfo* assert_info,
+ const CustomClientInfo& custom_client_info)
+ : crash_server_(crash_server),
+ pid_(pid),
+ dump_type_(dump_type),
+ ex_info_(ex_info),
+ assert_info_(assert_info),
+ custom_client_info_(custom_client_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) {
+ GetSystemTimeAsFileTime(&start_time_);
+}
+
+bool ClientInfo::Initialize() {
+ process_handle_ = OpenProcess(GENERIC_ALL, 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 (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);
+ }
+
+ if (process_handle_) {
+ CloseHandle(process_handle_);
+ }
+
+ if (dump_requested_handle_) {
+ CloseHandle(dump_requested_handle_);
+ }
+
+ if (dump_generated_handle_) {
+ CloseHandle(dump_generated_handle_);
+ }
+}
+
+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);
+}
+
+void ClientInfo::SetProcessUptime() {
+ FILETIME now = {0};
+ GetSystemTimeAsFileTime(&now);
+
+ ULARGE_INTEGER time_start;
+ time_start.HighPart = start_time_.dwHighDateTime;
+ time_start.LowPart = start_time_.dwLowDateTime;
+
+ ULARGE_INTEGER time_now;
+ time_now.HighPart = now.dwHighDateTime;
+ time_now.LowPart = now.dwLowDateTime;
+
+ // Calculate the delay and convert it from 100-nanoseconds to milliseconds.
+ __int64 delay = (time_now.QuadPart - time_start.QuadPart) / 10 / 1000;
+
+ // Convert it to a string.
+ wchar_t* value = custom_info_entries_.get()[custom_client_info_.count].value;
+ _i64tow_s(delay, value, CustomInfoEntry::kValueMaxLength, 10);
+}
+
+bool ClientInfo::PopulateCustomInfo() {
+ SIZE_T bytes_count = 0;
+ SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count;
+
+ // If the scoped array for custom info already has an array, it will be
+ // the same size as what we need. This is because the number of custom info
+ // entries is always the same. So allocate memory only if scoped array has
+ // a NULL pointer.
+ if (!custom_info_entries_.get()) {
+ // Allocate an extra entry for reporting uptime for the client process.
+ custom_info_entries_.reset(
+ new CustomInfoEntry[custom_client_info_.count + 1]);
+ // Use the last element in the array for uptime.
+ custom_info_entries_.get()[custom_client_info_.count].set_name(
+ kCustomInfoProcessUptimeName);
+ }
+
+ if (!ReadProcessMemory(process_handle_,
+ custom_client_info_.entries,
+ custom_info_entries_.get(),
+ read_count,
+ &bytes_count)) {
+ return false;
+ }
+
+ SetProcessUptime();
+ return (bytes_count != read_count);
+}
+
+CustomClientInfo ClientInfo::GetCustomInfo() const {
+ CustomClientInfo custom_info;
+ custom_info.entries = custom_info_entries_.get();
+ // Add 1 to the count from the client process to account for extra entry for
+ // process uptime.
+ custom_info.count = custom_client_info_.count + 1;
+ return custom_info;
+}
+
+} // namespace google_breakpad
Added: trunk/google-breakpad/src/client/windows/crash_generation/client_info.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/client_info.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,170 @@
+// 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 "client/windows/common/ipc_protocol.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "processor/scoped_ptr.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,
+ const CustomClientInfo& custom_client_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;
+
+ // Reads the custom information from the client process address space.
+ bool PopulateCustomInfo();
+
+ // Returns the client custom information.
+ CustomClientInfo GetCustomInfo() const;
+
+ private:
+ // Calcualtes the uptime for the client process, converts it to a string and
+ // stores it in the last entry of client custom info.
+ void SetProcessUptime();
+
+ // 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_;
+
+ // Custom information about the client.
+ CustomClientInfo custom_client_info_;
+
+ // Contains the custom client info entries read from the client process
+ // memory. This will be populated only if the method GetClientCustomInfo
+ // is called.
+ scoped_array<CustomInfoEntry> custom_info_entries_;
+
+ // 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_;
+
+ // Time when the client process started. It is used to determine the uptime
+ // for the client process when it signals a crash.
+ FILETIME start_time_;
+
+ // 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__
Added: trunk/google-breakpad/src/client/windows/crash_generation/crash_generation.vcproj
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/crash_generation.vcproj Sun Oct 19 13:26:38 2008
@@ -0,0 +1,347 @@
+<?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>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.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>
Added: trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,337 @@
+// 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 <utility>
+#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,
+ const CustomClientInfo* custom_info)
+ : 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),
+ custom_info_() {
+ memset(&assert_info_, 0, sizeof(assert_info_));
+ if (custom_info) {
+ custom_info_ = *custom_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_,
+ custom_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
Added: trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,159 @@
+// 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 <windows.h>
+#include <dbghelp.h>
+#include <string>
+#include <utility>
+#include "client/windows/common/ipc_protocol.h"
+#include "processor/scoped_ptr.h"
+
+namespace google_breakpad {
+
+struct CustomClientInfo;
+
+// 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,
+ const CustomClientInfo* custom_info);
+
+ ~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_;
+
+ // Custom client information
+ CustomClientInfo custom_info_;
+
+ // 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__
Added: trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,831 @@
+// 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 <list>
+#include "client/windows/common/auto_critical_section.h"
+#include "processor/scoped_ptr.h"
+
+namespace google_breakpad {
+
+// Output buffer size.
+static const size_t kOutBufferSize = 64;
+
+// Input buffer size.
+static const size_t kInBufferSize = 64;
+
+// Access flags for the client on the dump request event.
+static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE;
+
+// Access flags for the client on the dump generated event.
+static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE |
+ SYNCHRONIZE;
+
+// Access flags for the client on the mutex.
+static const DWORD kMutexAccess = SYNCHRONIZE;
+
+// Attribute flags for the pipe.
+static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE |
+ PIPE_ACCESS_DUPLEX |
+ FILE_FLAG_OVERLAPPED;
+
+// Mode for the pipe.
+static 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.
+static 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.
+static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD |
+ WT_EXECUTELONGFUNCTION;
+
+// Maximum delay during server shutdown if some work items
+// are still executing.
+static const int kShutdownDelayMs = 10000;
+
+// Interval for each sleep during server shutdown.
+static const int kShutdownSleepIntervalMs = 5;
+
+static bool IsClientRequestValid(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 std::wstring& pipe_name,
+ SECURITY_ATTRIBUTES* pipe_sec_attrs,
+ 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_sec_attrs_(pipe_sec_attrs),
+ 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,
+ pipe_sec_attrs_);
+ if (pipe_ == INVALID_HANDLE_VALUE) {
+ 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 = 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 (!IsClientRequestValid(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,
+ msg_.custom_client_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 = 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);
+ client_info->PopulateCustomInfo();
+
+ 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.
+ std::wstring dump_path;
+ if (generate_dumps_) {
+ if (!GenerateDump(client_info, &dump_path)) {
+ return;
+ }
+ }
+
+ if (dump_callback_) {
+ std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path;
+ dump_callback_(dump_context_, &client_info, ptr_dump_path);
+ }
+
+ SetEvent(client_info.dump_generated_handle());
+}
+
+bool CrashGenerationServer::GenerateDump(const ClientInfo& client,
+ std::wstring* dump_path) {
+ 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,
+ dump_path);
+}
+
+} // namespace google_breakpad
Added: trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,269 @@
+// 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 for Windows platform only. It generates Windows
+// minidump files for client processes that request dump generation. When
+// the server is requested to start listening for clients (by calling the
+// Start method), it creates a named pipe and waits for the clients to
+// register. In response, it hands them event handles that the client can
+// signal to request dump generation. When the clients request dump
+// generation in this way, the server generates Windows minidump files.
+class CrashGenerationServer {
+ public:
+ typedef void (*OnClientConnectedCallback)(void* context,
+ const ClientInfo* client_info);
+
+ typedef void (*OnClientDumpRequestCallback)(void* context,
+ const ClientInfo* client_info,
+ const std::wstring* file_path);
+
+ typedef void (*OnClientExitedCallback)(void* context,
+ const ClientInfo* client_info);
+
+ // Creates an instance with the given parameters.
+ //
+ // Parameter pipe_name: Name of the Windows named pipe
+ // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass
+ // NULL to use default security on the pipe. By default, the pipe created
+ // allows Local System, Administrators and the Creator full control and
+ // the Everyone group read access on 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.
+ // 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 std::wstring& pipe_name,
+ SECURITY_ATTRIBUTES* pipe_sec_attrs,
+ 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, std::wstring* dump_path);
+
+ // 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_;
+
+ // Pipe security attributes
+ SECURITY_ATTRIBUTES* pipe_sec_attrs_;
+
+ // 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.
+ 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__
Added: trunk/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,289 @@
+// 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,
+ wstring* dump_path) {
+ MiniDumpWriteDumpType write_dump = GetWriteDump();
+ if (!write_dump) {
+ return false;
+ }
+
+ wstring dump_file_path;
+ if (!GenerateDumpFilePath(&dump_file_path)) {
+ return false;
+ }
+
+ // If the client requests a full memory dump, we will write a normal mini
+ // dump and a full memory dump. Both dump files use the same uuid as file
+ // name prefix.
+ bool full_memory_dump = (dump_type & MiniDumpWithFullMemory) != 0;
+ wstring full_dump_file_path;
+ if (full_memory_dump) {
+ full_dump_file_path.assign(dump_file_path);
+ full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp
+ full_dump_file_path.append(TEXT("-full.dmp"));
+ }
+
+ 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;
+ }
+
+ HANDLE full_dump_file = INVALID_HANDLE_VALUE;
+ if (full_memory_dump) {
+ full_dump_file = CreateFile(full_dump_file_path.c_str(),
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (full_dump_file == INVALID_HANDLE_VALUE) {
+ CloseHandle(dump_file);
+ 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 = {0};
+ if (!is_client_pointers) {
+ // Set the dump thread id and requesting thread id only in case of
+ // in-process dump generation.
+ 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);
+ if (full_dump_file != INVALID_HANDLE_VALUE)
+ CloseHandle(full_dump_file);
+ return false;
+ }
+
+ if (bytes_read != sizeof(client_assert_info)) {
+ CloseHandle(dump_file);
+ if (full_dump_file != INVALID_HANDLE_VALUE)
+ CloseHandle(full_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_minidump = write_dump(
+ process_handle,
+ process_id,
+ dump_file,
+ static_cast<MINIDUMP_TYPE>((dump_type & (~MiniDumpWithFullMemory))
+ | MiniDumpNormal),
+ exception_pointers ? &dump_exception_info : NULL,
+ &user_streams,
+ NULL) != FALSE;
+
+ bool result_full_memory = true;
+ if (full_memory_dump) {
+ result_full_memory = write_dump(
+ process_handle,
+ process_id,
+ full_dump_file,
+ static_cast<MINIDUMP_TYPE>(dump_type & (~MiniDumpNormal)),
+ exception_pointers ? &dump_exception_info : NULL,
+ &user_streams,
+ NULL) != FALSE;
+ }
+
+ bool result = result_minidump && result_full_memory;
+
+ CloseHandle(dump_file);
+ if (full_dump_file != INVALID_HANDLE_VALUE)
+ CloseHandle(full_dump_file);
+
+ // Store the path of the dump file in the out parameter if dump generation
+ // succeeded.
+ if (result && dump_path) {
+ *dump_path = dump_file_path;
+ }
+
+ 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
Added: trunk/google-breakpad/src/client/windows/crash_generation/minidump_generator.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/client/windows/crash_generation/minidump_generator.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,121 @@
+// 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. Stores the
+ // dump file path in the dump_path parameter if dump generation
+ // succeeds.
+ 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,
+ std::wstring* dump_path);
+
+ 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__
Modified: trunk/google-breakpad/src/client/windows/handler/exception_handler.cc
==============================================================================
--- trunk/google-breakpad/src/client/windows/handler/exception_handler.cc (original)
+++ trunk/google-breakpad/src/client/windows/handler/exception_handler.cc Sun Oct 19 13:26:38 2008
@@ -34,6 +34,7 @@
#include "common/windows/string_utils-inl.h"
+#include "client/windows/common/ipc_protocol.h"
#include "client/windows/handler/exception_handler.h"
#include "common/windows/guid_string.h"
@@ -41,67 +42,132 @@
static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
-vector<ExceptionHandler *> *ExceptionHandler::handler_stack_ = NULL;
+vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
LONG ExceptionHandler::handler_stack_index_ = 0;
CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_;
bool ExceptionHandler::handler_stack_critical_section_initialized_ = false;
+ExceptionHandler::ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ const CustomClientInfo* custom_info) {
+ Initialize(dump_path,
+ filter,
+ callback,
+ callback_context,
+ handler_types,
+ dump_type,
+ pipe_name,
+ custom_info);
+}
+
ExceptionHandler::ExceptionHandler(const wstring &dump_path,
FilterCallback filter,
MinidumpCallback callback,
- void *callback_context,
- int handler_types)
- : filter_(filter),
- callback_(callback),
- callback_context_(callback_context),
- dump_path_(),
- next_minidump_id_(),
- next_minidump_path_(),
- dump_path_c_(),
- next_minidump_id_c_(NULL),
- next_minidump_path_c_(NULL),
- dbghelp_module_(NULL),
- minidump_write_dump_(NULL),
- handler_types_(handler_types),
- previous_filter_(NULL),
- previous_pch_(NULL),
- handler_thread_(0),
- handler_critical_section_(),
- handler_start_semaphore_(NULL),
- handler_finish_semaphore_(NULL),
- requesting_thread_id_(0),
- exception_info_(NULL),
- assertion_(NULL),
- handler_return_value_(false) {
+ void* callback_context,
+ int handler_types) {
+ Initialize(dump_path,
+ filter,
+ callback,
+ callback_context,
+ handler_types,
+ MiniDumpNormal,
+ NULL,
+ NULL);
+}
+
+void ExceptionHandler::Initialize(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ const CustomClientInfo* custom_info) {
+ filter_ = filter;
+ callback_ = callback;
+ callback_context_ = callback_context;
+ dump_path_c_ = NULL;
+ next_minidump_id_c_ = NULL;
+ next_minidump_path_c_ = NULL;
+ dbghelp_module_ = NULL;
+ minidump_write_dump_ = NULL;
+ dump_type_ = dump_type;
+ rpcrt4_module_ = NULL;
+ uuid_create_ = NULL;
+ handler_types_ = handler_types;
+ previous_filter_ = NULL;
#if _MSC_VER >= 1400 // MSVC 2005/8
previous_iph_ = NULL;
#endif // _MSC_VER >= 1400
+ previous_pch_ = NULL;
+ handler_thread_ = NULL;
+ handler_start_semaphore_ = NULL;
+ handler_finish_semaphore_ = NULL;
+ requesting_thread_id_ = 0;
+ exception_info_ = NULL;
+ assertion_ = NULL;
+ handler_return_value_ = false;
+ handle_debug_exceptions_ = false;
- // set_dump_path calls UpdateNextID. This sets up all of the path and id
- // strings, and their equivalent c_str pointers.
- set_dump_path(dump_path);
-
- // Set synchronization primitives and the handler thread. Each
- // ExceptionHandler object gets its own handler thread because that's the
- // only way to reliably guarantee sufficient stack space in an exception,
- // and it allows an easy way to get a snapshot of the requesting thread's
- // context outside of an exception.
- InitializeCriticalSection(&handler_critical_section_);
- handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
- handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
-
- DWORD thread_id;
- handler_thread_ = CreateThread(NULL, // lpThreadAttributes
- kExceptionHandlerThreadInitialStackSize,
- ExceptionHandlerThreadMain,
- this, // lpParameter
- 0, // dwCreationFlags
- &thread_id);
+ // Attempt to use out-of-process if user has specified pipe name.
+ if (pipe_name != NULL) {
+ scoped_ptr<CrashGenerationClient> client(
+ new CrashGenerationClient(pipe_name,
+ dump_type_,
+ custom_info));
+
+ // If successful in registering with the monitoring process,
+ // there is no need to setup in-process crash generation.
+ if (client->Register()) {
+ crash_generation_client_.reset(client.release());
+ }
+ }
- dbghelp_module_ = LoadLibrary(L"dbghelp.dll");
- if (dbghelp_module_) {
- minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>(
- GetProcAddress(dbghelp_module_, "MiniDumpWriteDump"));
+ if (!IsOutOfProcess()) {
+ // Either client did not ask for out-of-process crash generation
+ // or registration with the server process failed. In either case,
+ // setup to do in-process crash generation.
+
+ // Set synchronization primitives and the handler thread. Each
+ // ExceptionHandler object gets its own handler thread because that's the
+ // only way to reliably guarantee sufficient stack space in an exception,
+ // and it allows an easy way to get a snapshot of the requesting thread's
+ // context outside of an exception.
+ InitializeCriticalSection(&handler_critical_section_);
+ handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+ handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+
+ DWORD thread_id;
+ handler_thread_ = CreateThread(NULL, // lpThreadAttributes
+ kExceptionHandlerThreadInitialStackSize,
+ ExceptionHandlerThreadMain,
+ this, // lpParameter
+ 0, // dwCreationFlags
+ &thread_id);
+
+ dbghelp_module_ = LoadLibrary(L"dbghelp.dll");
+ if (dbghelp_module_) {
+ minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>(
+ GetProcAddress(dbghelp_module_, "MiniDumpWriteDump"));
+ }
+
+ // Load this library dynamically to not affect existing projects. Most
+ // projects don't link against this directly, it's usually dynamically
+ // loaded by dependent code.
+ rpcrt4_module_ = LoadLibrary(L"rpcrt4.dll");
+ if (rpcrt4_module_) {
+ uuid_create_ = reinterpret_cast<UuidCreate_type>(
+ GetProcAddress(rpcrt4_module_, "UuidCreate"));
+ }
+
+ // set_dump_path calls UpdateNextID. This sets up all of the path and id
+ // strings, and their equivalent c_str pointers.
+ set_dump_path(dump_path);
}
if (handler_types != HANDLER_NONE) {
@@ -115,7 +181,7 @@
// The first time an ExceptionHandler that installs a handler is
// created, set up the handler stack.
if (!handler_stack_) {
- handler_stack_ = new vector<ExceptionHandler *>();
+ handler_stack_ = new vector<ExceptionHandler*>();
}
handler_stack_->push_back(this);
@@ -139,6 +205,10 @@
FreeLibrary(dbghelp_module_);
}
+ if (rpcrt4_module_) {
+ FreeLibrary(rpcrt4_module_);
+ }
+
if (handler_types_ != HANDLER_NONE) {
EnterCriticalSection(&handler_stack_critical_section_);
@@ -159,7 +229,7 @@
// TODO(mmentovai): use advapi32!ReportEvent to log the warning to the
// system's application event log.
fprintf(stderr, "warning: removing Breakpad handler out of order\n");
- for (vector<ExceptionHandler *>::iterator iterator =
+ for (vector<ExceptionHandler*>::iterator iterator =
handler_stack_->begin();
iterator != handler_stack_->end();
++iterator) {
@@ -179,16 +249,20 @@
LeaveCriticalSection(&handler_stack_critical_section_);
}
- // Clean up the handler thread and synchronization primitives.
- TerminateThread(handler_thread_, 1);
- DeleteCriticalSection(&handler_critical_section_);
- CloseHandle(handler_start_semaphore_);
- CloseHandle(handler_finish_semaphore_);
+ // Some of the objects were only initialized if out of process
+ // registration was not done.
+ if (!IsOutOfProcess()) {
+ // Clean up the handler thread and synchronization primitives.
+ TerminateThread(handler_thread_, 1);
+ DeleteCriticalSection(&handler_critical_section_);
+ CloseHandle(handler_start_semaphore_);
+ CloseHandle(handler_finish_semaphore_);
+ }
}
// static
-DWORD ExceptionHandler::ExceptionHandlerThreadMain(void *lpParameter) {
- ExceptionHandler *self = reinterpret_cast<ExceptionHandler *>(lpParameter);
+DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) {
+ ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter);
assert(self);
while (true) {
@@ -260,32 +334,55 @@
LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
}
- ExceptionHandler *get_handler() const { return handler_; }
+ ExceptionHandler* get_handler() const { return handler_; }
private:
- ExceptionHandler *handler_;
+ ExceptionHandler* handler_;
};
// static
-LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS *exinfo) {
+LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) {
AutoExceptionHandler auto_exception_handler;
- ExceptionHandler *current_handler = auto_exception_handler.get_handler();
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
// Ignore EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP exceptions. This
// logic will short-circuit before calling WriteMinidumpOnHandlerThread,
// allowing something else to handle the breakpoint without incurring the
- // overhead transitioning to and from the handler thread.
+ // overhead transitioning to and from the handler thread. This behavior
+ // can be overridden by calling ExceptionHandler::set_handle_debug_exceptions.
DWORD code = exinfo->ExceptionRecord->ExceptionCode;
LONG action;
- if (code != EXCEPTION_BREAKPOINT && code != EXCEPTION_SINGLE_STEP &&
- current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL)) {
- // The handler fully handled the exception. Returning
- // EXCEPTION_EXECUTE_HANDLER indicates this to the system, and usually
- // results in the applicaiton being terminated.
- //
- // Note: If the application was launched from within the Cygwin
- // environment, returning EXCEPTION_EXECUTE_HANDLER seems to cause the
- // application to be restarted.
+ bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) ||
+ (code == EXCEPTION_SINGLE_STEP);
+
+ bool success = false;
+
+ if (!is_debug_exception ||
+ current_handler->get_handle_debug_exceptions()) {
+ // If out-of-proc crash handler client is available, we have to use that
+ // to generate dump and we cannot fall back on in-proc dump generation
+ // because we never prepared for an in-proc dump generation
+
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (current_handler->IsOutOfProcess()) {
+ success = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(),
+ exinfo,
+ NULL);
+ } else {
+ success = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL);
+ }
+ }
+
+ // The handler fully handled the exception. Returning
+ // EXCEPTION_EXECUTE_HANDLER indicates this to the system, and usually
+ // results in the application being terminated.
+ //
+ // Note: If the application was launched from within the Cygwin
+ // environment, returning EXCEPTION_EXECUTE_HANDLER seems to cause the
+ // application to be restarted.
+ if (success) {
action = EXCEPTION_EXECUTE_HANDLER;
} else {
// There was an exception, it was a breakpoint or something else ignored
@@ -308,35 +405,51 @@
#if _MSC_VER >= 1400 // MSVC 2005/8
// static
-void ExceptionHandler::HandleInvalidParameter(const wchar_t *expression,
- const wchar_t *function,
- const wchar_t *file,
+void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
unsigned int line,
uintptr_t reserved) {
// This is an invalid parameter, not an exception. It's safe to play with
// sprintf here.
AutoExceptionHandler auto_exception_handler;
- ExceptionHandler *current_handler = auto_exception_handler.get_handler();
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
MDRawAssertionInfo assertion;
memset(&assertion, 0, sizeof(assertion));
- _snwprintf_s(reinterpret_cast<wchar_t *>(assertion.expression),
+ _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.expression),
sizeof(assertion.expression) / sizeof(assertion.expression[0]),
_TRUNCATE, L"%s", expression);
- _snwprintf_s(reinterpret_cast<wchar_t *>(assertion.function),
+ _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.function),
sizeof(assertion.function) / sizeof(assertion.function[0]),
_TRUNCATE, L"%s", function);
- _snwprintf_s(reinterpret_cast<wchar_t *>(assertion.file),
+ _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.file),
sizeof(assertion.file) / sizeof(assertion.file[0]),
_TRUNCATE, L"%s", file);
assertion.line = line;
assertion.type = MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER;
- if (!current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion)) {
+ bool success = false;
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (current_handler->IsOutOfProcess()) {
+ success = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(),
+ NULL,
+ &assertion);
+ } else {
+ success = current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion);
+ }
+
+ if (!success) {
if (current_handler->previous_iph_) {
// The handler didn't fully handle the exception. Give it to the
// previous invalid parameter handler.
- current_handler->previous_iph_(expression, function, file, line, reserved);
+ current_handler->previous_iph_(expression,
+ function,
+ file,
+ line,
+ reserved);
} else {
// If there's no previous handler, pass the exception back in to the
// invalid parameter handler's core. That's the routine that called this
@@ -365,13 +478,26 @@
// static
void ExceptionHandler::HandlePureVirtualCall() {
AutoExceptionHandler auto_exception_handler;
- ExceptionHandler *current_handler = auto_exception_handler.get_handler();
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
MDRawAssertionInfo assertion;
memset(&assertion, 0, sizeof(assertion));
assertion.type = MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL;
- if (!current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion)) {
+ bool success = false;
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+
+ if (current_handler->IsOutOfProcess()) {
+ success = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(),
+ NULL,
+ &assertion);
+ } else {
+ success = current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion);
+ }
+
+ if (!success) {
if (current_handler->previous_pch_) {
// The handler didn't fully handle the exception. Give it to the
// previous purecall handler.
@@ -390,7 +516,7 @@
}
bool ExceptionHandler::WriteMinidumpOnHandlerThread(
- EXCEPTION_POINTERS *exinfo, MDRawAssertionInfo *assertion) {
+ EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) {
EnterCriticalSection(&handler_critical_section_);
// Set up data to be passed in to the handler thread.
@@ -419,7 +545,15 @@
return WriteMinidumpForException(NULL);
}
-bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS *exinfo) {
+bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) {
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (IsOutOfProcess()) {
+ return WriteMinidumpWithException(GetCurrentThreadId(),
+ exinfo,
+ NULL);
+ }
+
bool success = WriteMinidumpOnHandlerThread(exinfo, NULL);
UpdateNextID();
return success;
@@ -428,7 +562,7 @@
// static
bool ExceptionHandler::WriteMinidump(const wstring &dump_path,
MinidumpCallback callback,
- void *callback_context) {
+ void* callback_context) {
ExceptionHandler handler(dump_path, NULL, callback, callback_context,
HANDLER_NONE);
return handler.WriteMinidump();
@@ -436,8 +570,8 @@
bool ExceptionHandler::WriteMinidumpWithException(
DWORD requesting_thread_id,
- EXCEPTION_POINTERS *exinfo,
- MDRawAssertionInfo *assertion) {
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion) {
// Give user code a chance to approve or prevent writing a minidump. If the
// filter returns false, don't handle the exception at all. If this method
// was called as a result of an exception, returning false will cause
@@ -449,63 +583,77 @@
}
bool success = false;
- if (minidump_write_dump_) {
- HANDLE dump_file = CreateFile(next_minidump_path_c_,
- GENERIC_WRITE,
- 0, // no sharing
- NULL,
- CREATE_NEW, // fail if exists
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (dump_file != INVALID_HANDLE_VALUE) {
- MINIDUMP_EXCEPTION_INFORMATION except_info;
- except_info.ThreadId = requesting_thread_id;
- except_info.ExceptionPointers = exinfo;
- except_info.ClientPointers = FALSE;
-
- // 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 = GetCurrentThreadId();
- 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;
-
- if (assertion) {
- user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM;
- user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo);
- user_stream_array[1].Buffer = assertion;
- ++user_streams.UserStreamCount;
- }
+ if (IsOutOfProcess()) {
+ // Use the EXCEPTION_POINTERS overload for RequestDump if
+ // both exinfo and assertion are NULL.
+ if (!assertion) {
+ success = crash_generation_client_->RequestDump(exinfo);
+ } else {
+ success = crash_generation_client_->RequestDump(assertion);
+ }
+ } else {
+ if (minidump_write_dump_) {
+ HANDLE dump_file = CreateFile(next_minidump_path_c_,
+ GENERIC_WRITE,
+ 0, // no sharing
+ NULL,
+ CREATE_NEW, // fail if exists
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (dump_file != INVALID_HANDLE_VALUE) {
+ MINIDUMP_EXCEPTION_INFORMATION except_info;
+ except_info.ThreadId = requesting_thread_id;
+ except_info.ExceptionPointers = exinfo;
+ except_info.ClientPointers = FALSE;
+
+ // 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 = GetCurrentThreadId();
+ 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;
+
+ if (assertion) {
+ user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM;
+ user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo);
+ user_stream_array[1].Buffer = assertion;
+ ++user_streams.UserStreamCount;
+ }
- // The explicit comparison to TRUE avoids a warning (C4800).
- success = (minidump_write_dump_(GetCurrentProcess(),
- GetCurrentProcessId(),
- dump_file,
- MiniDumpNormal,
- exinfo ? &except_info : NULL,
- &user_streams,
- NULL) == TRUE);
+ // The explicit comparison to TRUE avoids a warning (C4800).
+ success = (minidump_write_dump_(GetCurrentProcess(),
+ GetCurrentProcessId(),
+ dump_file,
+ dump_type_,
+ exinfo ? &except_info : NULL,
+ &user_streams,
+ NULL) == TRUE);
- CloseHandle(dump_file);
+ CloseHandle(dump_file);
+ }
}
}
if (callback_) {
+ // TODO(munjal): In case of out-of-process dump generation, both
+ // dump_path_c_ and next_minidump_id_ will be NULL. For out-of-process
+ // scenario, the server process ends up creating the dump path and dump
+ // id so they are not known to the client.
success = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
exinfo, assertion, success);
}
@@ -514,8 +662,11 @@
}
void ExceptionHandler::UpdateNextID() {
- GUID id;
- CoCreateGuid(&id);
+ assert(uuid_create_);
+ UUID id = {0};
+ if (uuid_create_) {
+ uuid_create_(&id);
+ }
next_minidump_id_ = GUIDString::GUIDToWString(&id);
next_minidump_id_c_ = next_minidump_id_.c_str();
Modified: trunk/google-breakpad/src/client/windows/handler/exception_handler.h
==============================================================================
--- trunk/google-breakpad/src/client/windows/handler/exception_handler.h (original)
+++ trunk/google-breakpad/src/client/windows/handler/exception_handler.h Sun Oct 19 13:26:38 2008
@@ -52,9 +52,6 @@
// ExceptionHandler *f = new ExceptionHandler(...);
// delete e;
// This will put the exception filter stack into an inconsistent state.
-//
-// To use this library in your project, you will need to link against
-// ole32.lib.
#ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
#define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
@@ -62,15 +59,19 @@
#include <stdlib.h>
#include <Windows.h>
#include <DbgHelp.h>
+#include <rpc.h>
#pragma warning( push )
// Disable exception handler warnings.
-#pragma warning( disable : 4530 )
+#pragma warning( disable : 4530 )
#include <string>
#include <vector>
+#include "client/windows/common/ipc_protocol.h"
+#include "client/windows/crash_generation/crash_generation_client.h"
#include "google_breakpad/common/minidump_format.h"
+#include "processor/scoped_ptr.h"
namespace google_breakpad {
@@ -90,8 +91,8 @@
// attempting to write a minidump. If a FilterCallback returns false, Breakpad
// will immediately report the exception as unhandled without writing a
// minidump, allowing another handler the opportunity to handle it.
- typedef bool (*FilterCallback)(void *context, EXCEPTION_POINTERS *exinfo,
- MDRawAssertionInfo *assertion);
+ typedef bool (*FilterCallback)(void* context, EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion);
// A callback function to run after the minidump has been written.
// minidump_id is a unique id for the dump, so the minidump
@@ -112,11 +113,16 @@
// should normally return the value of |succeeded|, or when they wish to
// not report an exception of handled, false. Callbacks will rarely want to
// return true directly (unless |succeeded| is true).
- typedef bool (*MinidumpCallback)(const wchar_t *dump_path,
- const wchar_t *minidump_id,
- void *context,
- EXCEPTION_POINTERS *exinfo,
- MDRawAssertionInfo *assertion,
+ //
+ // For out-of-process dump generation, dump path and minidump ID will always
+ // be NULL. In case of out-of-process dump generation, the dump path and
+ // minidump id are controlled by the server process and are not communicated
+ // back to the crashing process.
+ typedef bool (*MinidumpCallback)(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
bool succeeded);
// HandlerType specifies which types of handlers should be installed, if
@@ -141,11 +147,26 @@
// minidump. Minidump files will be written to dump_path, and the optional
// callback is called after writing the dump file, as described above.
// handler_types specifies the types of handlers that should be installed.
- ExceptionHandler(const wstring &dump_path,
+ ExceptionHandler(const wstring& dump_path,
FilterCallback filter,
MinidumpCallback callback,
- void *callback_context,
+ void* callback_context,
int handler_types);
+
+ // Creates a new ExcetpionHandler instance that can attempt to perform
+ // out-of-process dump generation if pipe_name is not NULL. If pipe_name is
+ // NULL, or if out-of-process dump generation registration step fails,
+ // in-process dump generation will be used. This also allows specifying
+ // the dump type to generate.
+ ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ const CustomClientInfo* custom_info);
+
~ExceptionHandler();
// Get and set the minidump path.
@@ -162,12 +183,12 @@
// Writes a minidump immediately, with the user-supplied exception
// information.
- bool WriteMinidumpForException(EXCEPTION_POINTERS *exinfo);
+ bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo);
// Convenience form of WriteMinidump which does not require an
// ExceptionHandler instance.
static bool WriteMinidump(const wstring &dump_path,
- MinidumpCallback callback, void *callback_context);
+ MinidumpCallback callback, void* callback_context);
// Get the thread ID of the thread requesting the dump (either the exception
// thread or any other thread that called WriteMinidump directly). This
@@ -175,9 +196,28 @@
// dumps.
DWORD get_requesting_thread_id() const { return requesting_thread_id_; }
+ // Controls behavior of EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP.
+ bool get_handle_debug_exceptions() const { return handle_debug_exceptions_; }
+ void set_handle_debug_exceptions(bool handle_debug_exceptions) {
+ handle_debug_exceptions_ = handle_debug_exceptions;
+ }
+
+ // Returns whether out-of-process dump generation is used or not.
+ bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; }
+
private:
friend class AutoExceptionHandler;
+ // Initializes the instance with given values.
+ void Initialize(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ const CustomClientInfo* custom_info);
+
// Function pointer type for MiniDumpWriteDump, which is looked up
// dynamically.
typedef BOOL (WINAPI *MiniDumpWriteDump_type)(
@@ -189,12 +229,15 @@
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 *UuidCreate_type)(UUID* Uuid);
+
// Runs the main loop for the exception handler thread.
- static DWORD WINAPI ExceptionHandlerThreadMain(void *lpParameter);
+ static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter);
// Called on the exception thread when an unhandled exception occurs.
// Signals the exception handler thread to handle the exception.
- static LONG WINAPI HandleException(EXCEPTION_POINTERS *exinfo);
+ static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo);
#if _MSC_VER >= 1400 // MSVC 2005/8
// This function will be called by some CRT functions when they detect
@@ -202,9 +245,9 @@
// the CRT may display an assertion dialog before calling this function,
// and the function will not be called unless the assertion dialog is
// dismissed by clicking "Ignore."
- static void HandleInvalidParameter(const wchar_t *expression,
- const wchar_t *function,
- const wchar_t *file,
+ static void HandleInvalidParameter(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
unsigned int line,
uintptr_t reserved);
#endif // _MSC_VER >= 1400
@@ -222,8 +265,8 @@
// is NULL. If the dump is requested as a result of an assertion
// (such as an invalid parameter being passed to a CRT function),
// assertion contains data about the assertion, otherwise, it is NULL.
- bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS *exinfo,
- MDRawAssertionInfo *assertion);
+ bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion);
// This function does the actual writing of a minidump. It is called
// on the handler thread. requesting_thread_id is the ID of the thread
@@ -231,8 +274,8 @@
// an exception, exinfo contains exception information, otherwise,
// it is NULL.
bool WriteMinidumpWithException(DWORD requesting_thread_id,
- EXCEPTION_POINTERS *exinfo,
- MDRawAssertionInfo *assertion);
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion);
// Generates a new ID and stores it in next_minidump_id_, and stores the
// path of the next minidump to be written in next_minidump_path_.
@@ -240,7 +283,9 @@
FilterCallback filter_;
MinidumpCallback callback_;
- void *callback_context_;
+ void* callback_context_;
+
+ scoped_ptr<CrashGenerationClient> crash_generation_client_;
// The directory in which a minidump will be written, set by the dump_path
// argument to the constructor, or set_dump_path.
@@ -259,12 +304,16 @@
// pointers are not owned by the ExceptionHandler object, but their lifetimes
// should be equivalent to the lifetimes of the associated wstring, provided
// that the wstrings are not altered.
- const wchar_t *dump_path_c_;
- const wchar_t *next_minidump_id_c_;
- const wchar_t *next_minidump_path_c_;
+ const wchar_t* dump_path_c_;
+ const wchar_t* next_minidump_id_c_;
+ const wchar_t* next_minidump_path_c_;
HMODULE dbghelp_module_;
MiniDumpWriteDump_type minidump_write_dump_;
+ MINIDUMP_TYPE dump_type_;
+
+ HMODULE rpcrt4_module_;
+ UuidCreate_type uuid_create_;
// Tracks the handler types that were installed according to the
// handler_types constructor argument.
@@ -312,22 +361,27 @@
// The exception info passed to the exception handler on the exception
// thread, if an exception occurred. NULL for user-requested dumps.
- EXCEPTION_POINTERS *exception_info_;
+ EXCEPTION_POINTERS* exception_info_;
// If the handler is invoked due to an assertion, this will contain a
// pointer to the assertion information. It is NULL at other times.
- MDRawAssertionInfo *assertion_;
+ MDRawAssertionInfo* assertion_;
// The return value of the handler, passed from the handler thread back to
// the requesting thread.
bool handler_return_value_;
+ // If true, the handler will intercept EXCEPTION_BREAKPOINT and
+ // EXCEPTION_SINGLE_STEP exceptions. Leave this false (the default)
+ // to not interfere with debuggers.
+ bool handle_debug_exceptions_;
+
// A stack of ExceptionHandler objects that have installed unhandled
// exception filters. This vector is used by HandleException to determine
// which ExceptionHandler object to route an exception to. When an
// ExceptionHandler is created with install_handler true, it will append
// itself to this list.
- static vector<ExceptionHandler *> *handler_stack_;
+ static vector<ExceptionHandler*>* handler_stack_;
// The index of the ExceptionHandler in handler_stack_ that will handle the
// next exception. Note that 0 means the last entry in handler_stack_, 1
Modified: trunk/google-breakpad/src/client/windows/handler/exception_handler.vcproj
==============================================================================
--- trunk/google-breakpad/src/client/windows/handler/exception_handler.vcproj (original)
+++ trunk/google-breakpad/src/client/windows/handler/exception_handler.vcproj Sun Oct 19 13:26:38 2008
@@ -1,315 +1,323 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="exception_handler"
- ProjectGUID="{B55CA863-B374-4BAF-95AC-539E4FA4C90C}"
- RootNamespace="exception_handler"
- 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"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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"
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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=".\exception_handler.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\guid_string.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath=".\exception_handler.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\guid_string.h"
- >
- </File>
- <File
- RelativePath="..\..\..\google_breakpad\common\minidump_format.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils-inl.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>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="exception_handler"
+ ProjectGUID="{B55CA863-B374-4BAF-95AC-539E4FA4C90C}"
+ RootNamespace="exception_handler"
+ 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"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="crash_generation.lib"
+ AdditionalLibraryDirectories="..\$(ConfigurationName)"
+ />
+ <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"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="crash_generation.lib"
+ AdditionalLibraryDirectories="..\$(ConfigurationName)"
+ />
+ <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"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="crash_generation.lib"
+ AdditionalLibraryDirectories="..\$(ConfigurationName)"
+ />
+ <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"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="crash_generation.lib"
+ AdditionalLibraryDirectories="..\$(ConfigurationName)"
+ />
+ <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=".\exception_handler.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\exception_handler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\google_breakpad\common\minidump_format.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.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>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Modified: trunk/google-breakpad/src/client/windows/sender/crash_report_sender.cc
==============================================================================
--- trunk/google-breakpad/src/client/windows/sender/crash_report_sender.cc (original)
+++ trunk/google-breakpad/src/client/windows/sender/crash_report_sender.cc Sun Oct 19 13:26:38 2008
@@ -30,6 +30,8 @@
// Disable exception handler warnings.
#pragma warning( disable : 4530 )
+#include <errno.h>
+
#include "client/windows/sender/crash_report_sender.h"
#include "common/windows/http_upload.h"
@@ -69,9 +71,9 @@
bool result = HTTPUpload::SendRequest(
url, parameters, dump_file_name, L"upload_file_minidump", report_code,
&http_response);
- ReportSent(today);
if (result) {
+ ReportSent(today);
return RESULT_SUCCEEDED;
} else if (http_response == 400) { // TODO: update if/when the server
// switches to a different code
@@ -124,6 +126,9 @@
}
int CrashReportSender::OpenCheckpointFile(const wchar_t *mode, FILE **fd) {
+ if (checkpoint_file_.empty()) {
+ return ENOENT;
+ }
#if _MSC_VER >= 1400 // MSVC 2005/8
return _wfopen_s(fd, checkpoint_file_.c_str(), mode);
#else
Modified: trunk/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj
==============================================================================
--- trunk/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj (original)
+++ trunk/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj Sun Oct 19 13:26:38 2008
@@ -1,307 +1,307 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="crash_report_sender"
- ProjectGUID="{9946A048-043B-4F8F-9E07-9297B204714C}"
- RootNamespace="crash_report_sender"
- 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"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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"
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- 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=".\crash_report_sender.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\http_upload.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath=".\crash_report_sender.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\http_upload.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>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crash_report_sender"
+ ProjectGUID="{9946A048-043B-4F8F-9E07-9297B204714C}"
+ RootNamespace="crash_report_sender"
+ 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"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ 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"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ 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"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ 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"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ 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=".\crash_report_sender.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\crash_report_sender.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.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>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Modified: trunk/google-breakpad/src/common/linux/dump_symbols.cc
==============================================================================
--- trunk/google-breakpad/src/common/linux/dump_symbols.cc (original)
+++ trunk/google-breakpad/src/common/linux/dump_symbols.cc Sun Oct 19 13:26:38 2008
@@ -40,9 +40,11 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <algorithm>
#include <functional>
#include <vector>
+#include <string.h>
#include "common/linux/dump_symbols.h"
#include "common/linux/file_id.h"
@@ -54,6 +56,10 @@
// Infomation of a line.
struct LineInfo {
+ // The index into string table for the name of the source file which
+ // this line belongs to.
+ // Load from stab symbol.
+ uint32_t source_name_index;
// Offset from start of the function.
// Load from stab symbol.
ElfW(Off) rva_to_func;
@@ -65,6 +71,8 @@
uint32_t size;
// Line number.
uint32_t line_num;
+ // Id of the source file for this line.
+ int source_id;
};
// Information of a function.
@@ -82,14 +90,16 @@
uint32_t size;
// Total size of stack parameters.
uint32_t stack_param_size;
- // Is the function defined in included function?
- bool is_sol;
+ // Is there any lines included from other files?
+ bool has_sol;
// Line information array.
std::vector<struct LineInfo> line_info;
};
// Information of a source file.
struct SourceFileInfo {
+ // Name string index into the string table.
+ uint32_t name_index;
// Name of the source file.
const char *name;
// Starting address of the source file.
@@ -104,17 +114,17 @@
// This is the root of all types of symbol.
struct SymbolInfo {
std::vector<struct SourceFileInfo> source_file_info;
+
+ // The next source id for newly found source file.
+ int next_source_id;
};
// Stab section name.
-const char *kStabName = ".stab";
-
-// Stab str section name.
-const char *kStabStrName = ".stabstr";
+static const char *kStabName = ".stab";
// Demangle using abi call.
// Older GCC may not support it.
-std::string Demangle(const char *mangled) {
+static std::string Demangle(const char *mangled) {
int status = 0;
char *demangled = abi::__cxa_demangle(mangled, NULL, NULL, &status);
if (status == 0 && demangled != NULL) {
@@ -127,7 +137,7 @@
// Fix offset into virtual address by adding the mapped base into offsets.
// Make life easier when want to find something by offset.
-void FixAddress(void *obj_base) {
+static void FixAddress(void *obj_base) {
ElfW(Word) base = reinterpret_cast<ElfW(Word)>(obj_base);
ElfW(Ehdr) *elf_header = static_cast<ElfW(Ehdr) *>(obj_base);
elf_header->e_phoff += base;
@@ -138,7 +148,8 @@
}
// Find the prefered loading address of the binary.
-ElfW(Addr) GetLoadingAddress(const ElfW(Phdr) *program_headers, int nheader) {
+static ElfW(Addr) GetLoadingAddress(const ElfW(Phdr) *program_headers,
+ int nheader) {
for (int i = 0; i < nheader; ++i) {
const ElfW(Phdr) &header = program_headers[i];
// For executable, it is the PT_LOAD segment with offset to zero.
@@ -150,7 +161,7 @@
return 0;
}
-bool WriteFormat(int fd, const char *fmt, ...) {
+static bool WriteFormat(int fd, const char *fmt, ...) {
va_list list;
char buffer[4096];
ssize_t expected, written;
@@ -162,14 +173,14 @@
return expected == written;
}
-bool IsValidElf(const ElfW(Ehdr) *elf_header) {
+static bool IsValidElf(const ElfW(Ehdr) *elf_header) {
return memcmp(elf_header, ELFMAG, SELFMAG) == 0;
}
-const ElfW(Shdr) *FindSectionByName(const char *name,
- const ElfW(Shdr) *sections,
- const ElfW(Shdr) *strtab,
- int nsection) {
+static const ElfW(Shdr) *FindSectionByName(const char *name,
+ const ElfW(Shdr) *sections,
+ const ElfW(Shdr) *strtab,
+ int nsection) {
assert(name != NULL);
assert(sections != NULL);
assert(nsection > 0);
@@ -190,9 +201,9 @@
// TODO(liuli): Computer the stack parameter size.
// Expect parameter variables are immediately following the N_FUN symbol.
// Will need to parse the type information to get a correct size.
-int LoadStackParamSize(struct nlist *list,
- struct nlist *list_end,
- struct FuncInfo *func_info) {
+static int LoadStackParamSize(struct nlist *list,
+ struct nlist *list_end,
+ struct FuncInfo *func_info) {
struct nlist *cur_list = list;
assert(cur_list->n_type == N_FUN);
++cur_list;
@@ -205,26 +216,45 @@
return step;
}
-int LoadLineInfo(struct nlist *list,
- struct nlist *list_end,
- struct FuncInfo *func_info) {
+static int LoadLineInfo(struct nlist *list,
+ struct nlist *list_end,
+ const struct SourceFileInfo &source_file_info,
+ struct FuncInfo *func_info) {
struct nlist *cur_list = list;
- func_info->is_sol = false;
+ func_info->has_sol = false;
+ // Records which source file the following lines belongs. Default
+ // to the file we are handling. This helps us handling inlined source.
+ // When encountering N_SOL, we will change this to the source file
+ // specified by N_SOL.
+ int current_source_name_index = source_file_info.name_index;
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)
return cur_list - list;
- if (cur_list->n_type == N_SOL)
- func_info->is_sol = true;
+ // N_SOL means source lines following it will be from
+ // another source file.
+ if (cur_list->n_type == N_SOL) {
+ func_info->has_sol = true;
+
+ if (cur_list->n_un.n_strx > 0 &&
+ cur_list->n_un.n_strx != current_source_name_index) {
+ // The following lines will be from this source file.
+ current_source_name_index = cur_list->n_un.n_strx;
+ }
+ }
++cur_list;
}
struct LineInfo line;
while (cur_list < list_end && cur_list->n_type == N_SLINE) {
+ line.source_name_index = current_source_name_index;
line.rva_to_func = cur_list->n_value;
// n_desc is a signed short
line.line_num = (unsigned short)cur_list->n_desc;
+ // Don't set it here.
+ // Will be processed in later pass.
+ line.source_id = -1;
func_info->line_info.push_back(line);
++cur_list;
}
@@ -233,10 +263,10 @@
return cur_list - list;
}
-int LoadFuncSymbols(struct nlist *list,
- struct nlist *list_end,
- const ElfW(Shdr) *stabstr_section,
- struct SourceFileInfo *source_file_info) {
+static int LoadFuncSymbols(struct nlist *list,
+ struct nlist *list_end,
+ const ElfW(Shdr) *stabstr_section,
+ struct SourceFileInfo *source_file_info) {
struct nlist *cur_list = list;
assert(cur_list->n_type == N_SO);
++cur_list;
@@ -261,7 +291,10 @@
// Stack parameter size.
cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
// Line info.
- cur_list += LoadLineInfo(cur_list, list_end, &func_info);
+ cur_list += LoadLineInfo(cur_list,
+ list_end,
+ *source_file_info,
+ &func_info);
// Functions in this module should have address bigger than the module
// startring address.
// There maybe a lot of duplicated entry for a function in the symbol,
@@ -277,7 +310,7 @@
// Comapre the address.
// The argument should have a memeber named "addr"
template<class T1, class T2>
-bool CompareAddress(T1 *a, T2 *b) {
+static bool CompareAddress(T1 *a, T2 *b) {
return a->addr < b->addr;
}
@@ -285,7 +318,7 @@
// Return vector of pointers to the elements in the incoming array. So caller
// should make sure the returned vector lives longer than the incoming vector.
template<class T>
-std::vector<T *> SortByAddress(std::vector<T> *array) {
+static std::vector<T *> SortByAddress(std::vector<T> *array) {
std::vector<T *> sorted_array_ptr;
sorted_array_ptr.reserve(array->size());
for (size_t i = 0; i < array->size(); ++i)
@@ -299,9 +332,10 @@
// Find the address of the next function or source file symbol in the symbol
// table. The address should be bigger than the current function's address.
-ElfW(Addr) NextAddress(std::vector<struct FuncInfo *> *sorted_functions,
- std::vector<struct SourceFileInfo *> *sorted_files,
- const struct FuncInfo &func_info) {
+static ElfW(Addr) NextAddress(
+ std::vector<struct FuncInfo *> *sorted_functions,
+ std::vector<struct SourceFileInfo *> *sorted_files,
+ const struct FuncInfo &func_info) {
std::vector<struct FuncInfo *>::iterator next_func_iter =
std::find_if(sorted_functions->begin(),
sorted_functions->end(),
@@ -331,8 +365,68 @@
return 0;
}
+static int FindFileByNameIdx(uint32_t name_index,
+ const std::vector<SourceFileInfo> &files) {
+ for (size_t i = 0; i < files.size(); ++i) {
+ if (files[i].name_index == name_index)
+ return files[i].source_id;
+ }
+
+ return -1;
+}
+
+// Add included file information.
+// Also fix the source id for the line info.
+static void AddIncludedFiles(struct SymbolInfo *symbols,
+ const ElfW(Shdr) *stabstr_section) {
+ size_t source_file_size = symbols->source_file_info.size();
+
+ for (size_t i = 0; i < source_file_size; ++i) {
+ struct SourceFileInfo &source_file = symbols->source_file_info[i];
+
+ for (size_t j = 0; j < source_file.func_info.size(); ++j) {
+ struct FuncInfo &func_info = source_file.func_info[j];
+
+ for (size_t k = 0; k < func_info.line_info.size(); ++k) {
+ struct LineInfo &line_info = func_info.line_info[k];
+ assert(line_info.source_name_index > 0);
+ assert(source_file.name_index > 0);
+
+ // Check if the line belongs to the source file by comparing the
+ // name index into string table.
+ if (line_info.source_name_index != source_file.name_index) {
+ // This line is not from the current source file, check if this
+ // source file has been added before.
+ int found_source_id = FindFileByNameIdx(line_info.source_name_index,
+ symbols->source_file_info);
+ if (found_source_id < 0) {
+ // Got a new included file.
+ // Those included files don't have address or line information.
+ SourceFileInfo new_file;
+ new_file.name_index = line_info.source_name_index;
+ new_file.name = reinterpret_cast<char *>(new_file.name_index +
+ stabstr_section->sh_offset);
+ new_file.addr = 0;
+ new_file.source_id = symbols->next_source_id++;
+ line_info.source_id = new_file.source_id;
+ symbols->source_file_info.push_back(new_file);
+ } else {
+ // The file has been added.
+ line_info.source_id = found_source_id;
+ }
+ } else {
+ // The line belongs to the file.
+ line_info.source_id = source_file.source_id;
+ }
+ } // for each line.
+ } // for each function.
+ } // for each source file.
+
+}
+
// Compute size and rva information based on symbols loaded from stab section.
-bool ComputeSizeAndRVA(ElfW(Addr) loading_addr, struct SymbolInfo *symbols) {
+static bool ComputeSizeAndRVA(ElfW(Addr) loading_addr,
+ struct SymbolInfo *symbols) {
std::vector<struct SourceFileInfo *> sorted_files =
SortByAddress(&(symbols->source_file_info));
for (size_t i = 0; i < sorted_files.size(); ++i) {
@@ -410,17 +504,16 @@
return true;
}
-bool LoadSymbols(const ElfW(Shdr) *stab_section,
- const ElfW(Shdr) *stabstr_section,
- ElfW(Addr) loading_addr,
- struct SymbolInfo *symbols) {
+static bool LoadSymbols(const ElfW(Shdr) *stab_section,
+ const ElfW(Shdr) *stabstr_section,
+ ElfW(Addr) loading_addr,
+ struct SymbolInfo *symbols) {
if (stab_section == NULL || stabstr_section == NULL)
return false;
struct nlist *lists =
reinterpret_cast<struct nlist *>(stab_section->sh_offset);
int nstab = stab_section->sh_size / sizeof(struct nlist);
- int source_id = 0;
// First pass, load all symbols from the object file.
for (int i = 0; i < nstab; ) {
int step = 1;
@@ -428,11 +521,12 @@
if (cur_list->n_type == N_SO) {
// FUNC <address> <length> <param_stack_size> <function>
struct SourceFileInfo source_file_info;
+ source_file_info.name_index = cur_list->n_un.n_strx;
source_file_info.name = reinterpret_cast<char *>(cur_list->n_un.n_strx +
stabstr_section->sh_offset);
source_file_info.addr = cur_list->n_value;
if (strchr(source_file_info.name, '.'))
- source_file_info.source_id = source_id++;
+ source_file_info.source_id = symbols->next_source_id++;
else
source_file_info.source_id = -1;
step = LoadFuncSymbols(cur_list, lists + nstab,
@@ -441,11 +535,19 @@
}
i += step;
}
+
// Second pass, compute the size of functions and lines.
- return ComputeSizeAndRVA(loading_addr, symbols);
+ if (ComputeSizeAndRVA(loading_addr, symbols)) {
+ // Third pass, check for included source code, especially for header files.
+ // Until now, we only have compiling unit information, but they can
+ // have code from include files, add them here.
+ AddIncludedFiles(symbols, stabstr_section);
+ return true;
+ }
+ return false;
}
-bool LoadSymbols(ElfW(Ehdr) *elf_header, struct SymbolInfo *symbols) {
+static bool LoadSymbols(ElfW(Ehdr) *elf_header, struct SymbolInfo *symbols) {
// Translate all offsets in section headers into address.
FixAddress(elf_header);
ElfW(Addr) loading_addr = GetLoadingAddress(
@@ -467,7 +569,9 @@
return LoadSymbols(stab_section, stabstr_section, loading_addr, symbols);
}
-bool WriteModuleInfo(int fd, ElfW(Half) arch, const std::string &obj_file) {
+static bool WriteModuleInfo(int fd,
+ ElfW(Half) arch,
+ const std::string &obj_file) {
const char *arch_name = NULL;
if (arch == EM_386)
arch_name = "x86";
@@ -500,7 +604,7 @@
return false;
}
-bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) {
+static bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) {
for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
if (symbols.source_file_info[i].source_id != -1) {
const char *name = symbols.source_file_info[i].name;
@@ -512,8 +616,8 @@
return true;
}
-bool WriteOneFunction(int fd, int source_id,
- const struct FuncInfo &func_info){
+static bool WriteOneFunction(int fd,
+ const struct FuncInfo &func_info){
// Discard the ending part of the name.
std::string func_name(func_info.name);
std::string::size_type last_colon = func_name.find_last_of(':');
@@ -535,7 +639,7 @@
line_info.rva_to_base,
line_info.size,
line_info.line_num,
- source_id))
+ line_info.source_id))
return false;
}
return true;
@@ -543,19 +647,19 @@
return false;
}
-bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
+static bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
const struct SourceFileInfo &file_info = symbols.source_file_info[i];
for (size_t j = 0; j < file_info.func_info.size(); ++j) {
const struct FuncInfo &func_info = file_info.func_info[j];
- if (!WriteOneFunction(fd, file_info.source_id, func_info))
+ if (!WriteOneFunction(fd, func_info))
return false;
}
}
return true;
}
-bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) {
+static bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) {
return WriteSourceFileInfo(fd, symbols) &&
WriteFunctionInfo(fd, symbols);
}
@@ -617,7 +721,7 @@
namespace google_breakpad {
bool DumpSymbols::WriteSymbolFile(const std::string &obj_file,
- int sym_fd) {
+ int sym_fd) {
int obj_fd = open(obj_file.c_str(), O_RDONLY);
if (obj_fd < 0)
return false;
@@ -634,6 +738,8 @@
if (!IsValidElf(elf_header))
return false;
struct SymbolInfo symbols;
+ symbols.next_source_id = 0;
+
if (!LoadSymbols(elf_header, &symbols))
return false;
// Write to symbol file.
Modified: trunk/google-breakpad/src/common/linux/file_id.cc
==============================================================================
--- trunk/google-breakpad/src/common/linux/file_id.cc (original)
+++ trunk/google-breakpad/src/common/linux/file_id.cc Sun Oct 19 13:26:38 2008
@@ -42,7 +42,7 @@
#include <unistd.h>
#include "common/linux/file_id.h"
-#include "common/linux/md5.h"
+#include "common/md5.h"
namespace google_breakpad {
Modified: trunk/google-breakpad/src/common/linux/http_upload.cc
==============================================================================
--- trunk/google-breakpad/src/common/linux/http_upload.cc (original)
+++ trunk/google-breakpad/src/common/linux/http_upload.cc Sun Oct 19 13:26:38 2008
@@ -28,6 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cassert>
+#include <dlfcn.h>
#include <curl/curl.h>
#include <curl/easy.h>
#include <curl/types.h>
@@ -61,69 +62,107 @@
const string &file_part_name,
const string &proxy,
const string &proxy_user_pwd,
- string *response_body) {
+ string *response_body,
+ string *error_description) {
if (!CheckParameters(parameters))
return false;
- CURL *curl = curl_easy_init();
- CURLcode err_code = CURLE_OK;
+ void *curl_lib = dlopen("libcurl.so", RTLD_NOW);
+ if (!curl_lib) {
+ curl_lib = dlopen("libcurl.so.4", RTLD_NOW);
+ }
+ if (!curl_lib) {
+ curl_lib = dlopen("libcurl.so.3", RTLD_NOW);
+ }
+ if (!curl_lib) {
+ return false;
+ }
- if (curl) {
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- curl_easy_setopt(curl, CURLOPT_USERAGENT, kUserAgent);
- // Set proxy information if necessary.
- if (!proxy.empty())
- curl_easy_setopt(curl, CURLOPT_PROXY, proxy.c_str());
- if (!proxy_user_pwd.empty())
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str());
-
- struct curl_httppost *formpost = NULL;
- struct curl_httppost *lastptr = NULL;
- // Add form data.
- map<string, string>::const_iterator iter = parameters.begin();
- for (; iter != parameters.end(); ++iter)
- curl_formadd(&formpost, &lastptr,
- CURLFORM_COPYNAME, iter->first.c_str(),
- CURLFORM_COPYCONTENTS, iter->second.c_str(),
- CURLFORM_END);
-
- // Add form file.
- curl_formadd(&formpost, &lastptr,
- CURLFORM_COPYNAME, file_part_name.c_str(),
- CURLFORM_FILE, upload_file.c_str(),
- CURLFORM_END);
+ CURL* (*curl_easy_init)(void);
+ *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init");
+ CURL *curl = (*curl_easy_init)();
+ if (error_description != NULL)
+ *error_description = "No Error";
+
+ if (!curl) {
+ dlclose(curl_lib);
+ return false;
+ }
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+ CURLcode err_code = CURLE_OK;
+ CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...);
+ *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt");
+ (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str());
+ (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent);
+ // Set proxy information if necessary.
+ if (!proxy.empty())
+ (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str());
+ if (!proxy_user_pwd.empty())
+ (*curl_easy_setopt)(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str());
+
+ struct curl_httppost *formpost = NULL;
+ struct curl_httppost *lastptr = NULL;
+ // Add form data.
+ CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...);
+ *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd");
+ map<string, string>::const_iterator iter = parameters.begin();
+ for (; iter != parameters.end(); ++iter)
+ (*curl_formadd)(&formpost, &lastptr,
+ CURLFORM_COPYNAME, iter->first.c_str(),
+ CURLFORM_COPYCONTENTS, iter->second.c_str(),
+ CURLFORM_END);
- // Disable 100-continue header.
- struct curl_slist *headerlist = NULL;
- char buf[] = "Expect:";
- headerlist = curl_slist_append(headerlist, buf);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
-
- if (response_body != NULL) {
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA,
- reinterpret_cast<void *>(response_body));
- }
+ // Add form file.
+ (*curl_formadd)(&formpost, &lastptr,
+ CURLFORM_COPYNAME, file_part_name.c_str(),
+ CURLFORM_FILE, upload_file.c_str(),
+ CURLFORM_END);
+
+ (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost);
+
+ // Disable 100-continue header.
+ struct curl_slist *headerlist = NULL;
+ char buf[] = "Expect:";
+ struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *);
+ *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append");
+ headerlist = (*curl_slist_append)(headerlist, buf);
+ (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist);
+
+ if (response_body != NULL) {
+ (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+ (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA,
+ reinterpret_cast<void *>(response_body));
+ }
- err_code = curl_easy_perform(curl);
+ CURLcode (*curl_easy_perform)(CURL *);
+ *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform");
+ err_code = (*curl_easy_perform)(curl);
+ const char* (*curl_easy_strerror)(CURLcode);
+ *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror");
#ifndef NDEBUG
- if (err_code != CURLE_OK)
- fprintf(stderr, "Failed to send http request to %s, error: %s\n",
- url.c_str(),
- curl_easy_strerror(err_code));
+ if (err_code != CURLE_OK)
+ fprintf(stderr, "Failed to send http request to %s, error: %s\n",
+ url.c_str(),
+ (*curl_easy_strerror)(err_code));
#endif
+ if (error_description != NULL)
+ *error_description = (*curl_easy_strerror)(err_code);
- if (curl != NULL)
- curl_easy_cleanup(curl);
- if (formpost != NULL)
- curl_formfree(formpost);
- if (headerlist != NULL)
- curl_slist_free_all(headerlist);
- return err_code == CURLE_OK;
+ void (*curl_easy_cleanup)(CURL *);
+ *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup");
+ (*curl_easy_cleanup)(curl);
+ if (formpost != NULL) {
+ void (*curl_formfree)(struct curl_httppost *);
+ *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree");
+ (*curl_formfree)(formpost);
+ }
+ if (headerlist != NULL) {
+ void (*curl_slist_free_all)(struct curl_slist *);
+ *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all");
+ (*curl_slist_free_all)(headerlist);
}
- return false;
+ dlclose(curl_lib);
+ return err_code == CURLE_OK;
}
// static
Modified: trunk/google-breakpad/src/common/linux/http_upload.h
==============================================================================
--- trunk/google-breakpad/src/common/linux/http_upload.h (original)
+++ trunk/google-breakpad/src/common/linux/http_upload.h Sun Oct 19 13:26:38 2008
@@ -53,13 +53,16 @@
// Only HTTP(S) URLs are currently supported. Returns true on success.
// If the request is successful and response_body is non-NULL,
// the response body will be returned in response_body.
+ // If the send fails, a description of the error will be
+ // returned in error_description.
static bool SendRequest(const string &url,
const map<string, string> ¶meters,
const string &upload_file,
const string &file_part_name,
const string &proxy,
const string &proxy_user_pwd,
- string *response_body);
+ string *response_body,
+ string *error_description);
private:
// Checks that the given list of parameters has only printable
Modified: trunk/google-breakpad/src/common/mac/dump_syms.h
==============================================================================
--- trunk/google-breakpad/src/common/mac/dump_syms.h (original)
+++ trunk/google-breakpad/src/common/mac/dump_syms.h Sun Oct 19 13:26:38 2008
@@ -30,9 +30,14 @@
// dump_syms.h: Interface for DumpSymbols. This class will take a mach-o file
// and extract the symbol information and write it to a file using the
// breakpad symbol file format.
-// NOTE: Only Stabs format is currently supported -- not DWARF.
#import <Foundation/Foundation.h>
+#include <mach-o/loader.h>
+#include "common/mac/dwarf/dwarf2reader.h"
+
+// This will map from an architecture string to a SectionMap, which
+// will contain the offsets for all the sections in the dictionary
+typedef hash_map<string, dwarf2reader::SectionMap *> ArchSectionMap;
@interface DumpSymbols : NSObject {
@protected
@@ -43,8 +48,9 @@
NSMutableDictionary *sources_; // Address and Source file paths (STRONG)
NSMutableArray *cppAddresses_; // Addresses of C++ symbols (STRONG)
NSMutableDictionary *headers_; // Mach-o header information (STRONG)
- NSMutableDictionary *sectionNumbers_; // Keyed by seg/sect name (STRONG)
+ NSMutableDictionary *sectionData_; // Keyed by seg/sect name (STRONG)
uint32_t lastStartAddress_;
+ ArchSectionMap *sectionsForArch_;
}
- (id)initWithContentsOfFile:(NSString *)machoFile;
@@ -61,3 +67,14 @@
- (BOOL)writeSymbolFile:(NSString *)symbolFilePath;
@end
+
+ interface MachSection : NSObject {
+ @protected
+ struct section *sect_;
+ uint32_t sectionNumber_;
+}
+- (id)initWithMachSection:(struct section *)sect andNumber:(uint32_t)sectionNumber;
+- (struct section*)sectionPointer;
+- (uint32_t)sectionNumber;
+
+ end
Modified: trunk/google-breakpad/src/common/mac/dump_syms.mm
==============================================================================
--- trunk/google-breakpad/src/common/mac/dump_syms.mm (original)
+++ trunk/google-breakpad/src/common/mac/dump_syms.mm Sun Oct 19 13:26:38 2008
@@ -47,6 +47,9 @@
#import "dump_syms.h"
#import "common/mac/file_id.h"
#import "common/mac/macho_utilities.h"
+#import "common/mac/dwarf/dwarf2reader.h"
+#import "common/mac/dwarf/functioninfo.h"
+#import "common/mac/dwarf/bytereader.h"
using google_breakpad::FileID;
@@ -54,6 +57,7 @@
static NSString *kAddressConvertedSymbolKey = @"converted_symbol";
static NSString *kAddressSourceLineKey = @"line";
static NSString *kFunctionSizeKey = @"size";
+static NSString *kFunctionFileKey = @"source_file";
static NSString *kHeaderBaseAddressKey = @"baseAddr";
static NSString *kHeaderSizeKey = @"size";
static NSString *kHeaderOffsetKey = @"offset"; // Offset to the header
@@ -65,6 +69,40 @@
// for pruning out extraneous non-function symbols.
static const int kTextSection = 1;
+namespace __gnu_cxx {
+template<>
+ struct hash<std::string> {
+ size_t operator()(const std::string& k) const {
+ return hash< const char* >()( k.c_str() );
+ }
+};
+}
+
+// Dump FunctionMap to stdout. Print address, function name, file
+// name, line number, lowpc, and highpc if available.
+void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
+ for (dwarf2reader::FunctionMap::const_iterator iter = function_map.begin();
+ iter != function_map.end(); ++iter) {
+ if (iter->second->name.empty()) {
+ continue;
+ }
+ printf("%08llx: %s", iter->first,
+ iter->second->name.data());
+ if (!iter->second->file.empty()) {
+ printf(" - %s", iter->second->file.data());
+ if (iter->second->line != 0) {
+ printf(":%u", iter->second->line);
+ }
+ }
+ if (iter->second->lowpc != 0 && iter->second->highpc != 0) {
+ printf(" (%08llx - %08llx)\n",
+ iter->second->lowpc,
+ iter->second->highpc);
+ }
+ }
+}
+
+
@interface DumpSymbols(PrivateMethods)
- (NSArray *)convertCPlusPlusSymbols:(NSArray *)symbols;
- (void)convertSymbols;
@@ -73,10 +111,17 @@
- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset;
- (BOOL)loadSymbolInfo64:(void *)base offset:(uint32_t)offset;
- (BOOL)loadSymbolInfoForArchitecture;
+- (BOOL)loadDWARFSymbolInfo:(void *)base offset:(uint32_t)offset;
+- (BOOL)loadSTABSSymbolInfo:(void *)base offset:(uint32_t)offset;
- (void)generateSectionDictionary:(struct mach_header*)header;
- (BOOL)loadHeader:(void *)base offset:(uint32_t)offset;
- (BOOL)loadHeader64:(void *)base offset:(uint32_t)offset;
- (BOOL)loadModuleInfo;
+- (void)processDWARFLineNumberInfo:(dwarf2reader::LineMap*)line_map;
+- (void)processDWARFFunctionInfo:(dwarf2reader::FunctionMap*)address_to_funcinfo;
+- (void)processDWARFSourceFileInfo:(vector<dwarf2reader::SourceFileInfo>*) files;
+- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset;
+- (dwarf2reader::SectionMap*)getSectionMapForArchitecture:(NSString*)architecture;
@end
@implementation DumpSymbols
@@ -241,6 +286,7 @@
if (line && ![dict objectForKey:kAddressSourceLineKey])
[dict setObject:[NSNumber numberWithUnsignedInt:line]
forKey:kAddressSourceLineKey];
+
}
//=============================================================================
@@ -277,7 +323,9 @@
int line = list->n_desc;
// __TEXT __text section
- uint32_t mainSection = [[sectionNumbers_ objectForKey:@"__TEXT__text" ] unsignedLongValue];
+ NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_];
+
+ uint32_t mainSection = [[archSections objectForKey:@"__TEXT__text" ] sectionNumber];
// Extract debugging information:
// Doc: http://developer.apple.com/documentation/DeveloperTools/gdb/stabs/stabs_toc.html
@@ -287,6 +335,14 @@
NSString *ext = [src pathExtension];
NSNumber *address = [NSNumber numberWithUnsignedLongLong:list->n_value];
+ // Leopard puts .c files with no code as an offset of 0, but a
+ // crash can't happen here and it throws off our code that matches
+ // symbols to line numbers so we ignore them..
+ // Return YES because this isn't an error, just something we don't
+ // care to handle.
+ if ([address unsignedLongValue] == 0) {
+ return YES;
+ }
// TODO(waylonis):Ensure that we get the full path for the source file
// from the first N_SO record
// If there is an extension, we'll consider it source code
@@ -295,7 +351,6 @@
sources_ = [[NSMutableDictionary alloc] init];
// Save the source associated with an address
[sources_ setObject:src forKey:address];
-
result = YES;
}
} else if (list->n_type == N_FUN) {
@@ -313,7 +368,7 @@
[self addFunction:fn line:line address:list->n_value section:list->n_sect ];
result = YES;
- } else if (list->n_type == N_SLINE && list->n_sect == mainSection ) {
+ } else if (list->n_type == N_SLINE && list->n_sect == mainSection) {
[self addFunction:nil line:line address:list->n_value section:list->n_sect ];
result = YES;
} else if (((list->n_type & N_TYPE) == N_SECT) && !(list->n_type & N_STAB)) {
@@ -331,8 +386,169 @@
#define SwapLongIfNeeded(a) (swap ? NXSwapLong(a) : (a))
#define SwapIntIfNeeded(a) (swap ? NXSwapInt(a) : (a))
#define SwapShortIfNeeded(a) (swap ? NXSwapShort(a) : (a))
+
//=============================================================================
- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset {
+ NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_];
+ if ([archSections objectForKey:@"__DWARF__debug_info"]) {
+ // Treat this this as debug information
+ return [self loadDWARFSymbolInfo:base offset:offset];
+ }
+
+ return [self loadSTABSSymbolInfo:base offset:offset];
+}
+
+//=============================================================================
+- (BOOL)loadDWARFSymbolInfo:(void *)base offset:(uint32_t)offset {
+
+ struct mach_header *header = (struct mach_header *)
+ ((uint32_t)base + offset);
+ BOOL swap = (header->magic == MH_CIGAM);
+
+ NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_];
+ assert (archSections != nil);
+ section *dbgInfoSection = [[archSections objectForKey:@"__DWARF__debug_info"] sectionPointer];
+ uint32_t debugInfoSize = SwapLongIfNeeded(dbgInfoSection->size);
+
+ // i think this will break if run on a big-endian machine
+ dwarf2reader::ByteReader byte_reader(swap ?
+ dwarf2reader::ENDIANNESS_BIG :
+ dwarf2reader::ENDIANNESS_LITTLE);
+
+ uint64_t dbgOffset = 0;
+
+ dwarf2reader::SectionMap* oneArchitectureSectionMap = [self getSectionMapForArchitecture:architecture_];
+
+ while (dbgOffset < debugInfoSize) {
+ // Prepare necessary objects.
+ dwarf2reader::FunctionMap off_to_funcinfo;
+ dwarf2reader::FunctionMap address_to_funcinfo;
+ dwarf2reader::LineMap line_map;
+ vector<dwarf2reader::SourceFileInfo> files;
+ vector<string> dirs;
+
+ dwarf2reader::CULineInfoHandler line_info_handler(&files, &dirs,
+ &line_map);
+
+ dwarf2reader::CUFunctionInfoHandler function_info_handler(&files, &dirs,
+ &line_map,
+ &off_to_funcinfo,
+ &address_to_funcinfo,
+ &line_info_handler,
+ *oneArchitectureSectionMap,
+ &byte_reader);
+
+ dwarf2reader::CompilationUnit compilation_unit(*oneArchitectureSectionMap,
+ dbgOffset,
+ &byte_reader,
+ &function_info_handler);
+
+ dbgOffset += compilation_unit.Start();
+
+ // The next 3 functions take the info that the dwarf reader
+ // gives and massages them into the data structures that
+ // dump_syms uses
+ [self processDWARFSourceFileInfo:&files];
+ [self processDWARFFunctionInfo:&address_to_funcinfo];
+ [self processDWARFLineNumberInfo:&line_map];
+ }
+
+ return YES;
+}
+
+- (void)processDWARFSourceFileInfo:(vector<dwarf2reader::SourceFileInfo>*) files {
+ if (!sources_)
+ sources_ = [[NSMutableDictionary alloc] init];
+ // Save the source associated with an address
+ vector<dwarf2reader::SourceFileInfo>::const_iterator iter = files->begin();
+ for (; iter != files->end(); iter++) {
+ NSString *sourceFile = [NSString stringWithUTF8String:(*iter).name.c_str()];
+ if ((*iter).lowpc != ULLONG_MAX) {
+ NSNumber *address = [NSNumber numberWithUnsignedLongLong:(*iter).lowpc];
+ if ([address unsignedLongLongValue] == 0) {
+ continue;
+ }
+ [sources_ setObject:sourceFile forKey:address];
+ }
+ }
+}
+
+- (void)processDWARFFunctionInfo:(dwarf2reader::FunctionMap*)address_to_funcinfo {
+ for (dwarf2reader::FunctionMap::const_iterator iter = address_to_funcinfo->begin();
+ iter != address_to_funcinfo->end(); ++iter) {
+ if (iter->second->name.empty()) {
+ continue;
+ }
+
+ if (!addresses_)
+ addresses_ = [[NSMutableDictionary alloc] init];
+
+ NSNumber *addressNum = [NSNumber numberWithUnsignedLongLong:(*iter).second->lowpc];
+
+ [functionAddresses_ addObject:addressNum];
+
+ NSMutableDictionary *dict = [addresses_ objectForKey:addressNum];
+
+ if (!dict) {
+ dict = [[NSMutableDictionary alloc] init];
+ [addresses_ setObject:dict forKey:addressNum];
+ [dict release];
+ }
+
+ // set name of function if it isn't already set
+ if (![dict objectForKey:kAddressSymbolKey]) {
+ NSString *symbolName = [NSString stringWithUTF8String:iter->second->name.c_str()];
+ [dict setObject:symbolName forKey:kAddressSymbolKey];
+ }
+
+ // set line number for beginning of function
+ if (![dict objectForKey:kAddressSourceLineKey])
+ [dict setObject:[NSNumber numberWithUnsignedInt:iter->second->line]
+ forKey:kAddressSourceLineKey];
+
+ // set function size by subtracting low PC from high PC
+ if (![dict objectForKey:kFunctionSizeKey]) {
+ [dict setObject:[NSNumber numberWithUnsignedLongLong:iter->second->highpc - iter->second->lowpc]
+ forKey:kFunctionSizeKey];
+ }
+
+ // Set the file that the function is in
+ if (![dict objectForKey:kFunctionFileKey]) {
+ [dict setObject:[NSString stringWithUTF8String:iter->second->file.c_str()]
+ forKey:kFunctionFileKey];
+ }
+ }
+}
+
+- (void)processDWARFLineNumberInfo:(dwarf2reader::LineMap*)line_map {
+ for (dwarf2reader::LineMap::const_iterator iter = line_map->begin();
+ iter != line_map->end();
+ ++iter) {
+
+ NSNumber *addressNum = [NSNumber numberWithUnsignedLongLong:iter->first];
+ NSMutableDictionary *dict = [addresses_ objectForKey:addressNum];
+
+ if (!dict) {
+ dict = [[NSMutableDictionary alloc] init];
+ [addresses_ setObject:dict forKey:addressNum];
+ [dict release];
+ }
+
+ if (![dict objectForKey:kAddressSourceLineKey]) {
+ [dict setObject:[NSNumber numberWithUnsignedInt:iter->second.second]
+ forKey:kAddressSourceLineKey];
+ }
+
+ // Set the file that the function's address is in
+ if (![dict objectForKey:kFunctionFileKey]) {
+ [dict setObject:[NSString stringWithUTF8String:iter->second.first.c_str()]
+ forKey:kFunctionFileKey];
+ }
+ }
+}
+
+//=============================================================================
+- (BOOL)loadSTABSSymbolInfo:(void *)base offset:(uint32_t)offset {
struct mach_header *header = (struct mach_header *)((uint32_t)base + offset);
BOOL swap = (header->magic == MH_CIGAM);
uint32_t count = SwapLongIfNeeded(header->ncmds);
@@ -363,6 +579,8 @@
nlist64.n_desc = SwapShortIfNeeded(list->n_desc);
nlist64.n_value = (uint64_t)SwapLongIfNeeded(list->n_value);
+ // TODO(nealsid): is this broken? we get NO if one symbol fails
+ // but then we lose that information if another suceeeds
if ([self processSymbolItem:&nlist64 stringTable:strtab])
result = YES;
}
@@ -424,6 +642,7 @@
- (BOOL)loadSymbolInfoForArchitecture {
NSMutableData *data = [[NSMutableData alloc]
initWithContentsOfMappedFile:sourcePath_];
+
NSDictionary *headerInfo = [headers_ objectForKey:architecture_];
void *base = [data mutableBytes];
uint32_t offset =
@@ -436,10 +655,28 @@
return result;
}
+- (dwarf2reader::SectionMap*)getSectionMapForArchitecture:(NSString*)architecture {
+
+ string currentArch([architecture UTF8String]);
+ dwarf2reader::SectionMap *oneArchitectureSectionMap;
+
+ ArchSectionMap::const_iterator iter = sectionsForArch_->find(currentArch);
+
+ if (iter == sectionsForArch_->end()) {
+ oneArchitectureSectionMap = new dwarf2reader::SectionMap();
+ sectionsForArch_->insert(make_pair(currentArch, oneArchitectureSectionMap));
+ } else {
+ oneArchitectureSectionMap = iter->second;
+ }
+
+ return oneArchitectureSectionMap;
+}
+
//=============================================================================
// build a dictionary of section numbers keyed off a string
// which is the concatenation of the segment name and the section name
- (void)generateSectionDictionary:(struct mach_header*)header {
+
BOOL swap = (header->magic == MH_CIGAM);
uint32_t count = SwapLongIfNeeded(header->ncmds);
struct load_command *cmd =
@@ -447,8 +684,29 @@
uint32_t segmentCommand = SwapLongIfNeeded(LC_SEGMENT);
uint32_t sectionNumber = 1; // section numbers are counted from 1
- if (!sectionNumbers_)
- sectionNumbers_ = [[NSMutableDictionary alloc] init];
+ cpu_type_t cpu = SwapIntIfNeeded(header->cputype);
+
+ NSString *arch;
+
+ if (cpu & CPU_ARCH_ABI64)
+ arch = ((cpu & ~CPU_ARCH_ABI64) == CPU_TYPE_X86) ?
+ @"x86_64" : @"ppc64";
+ else
+ arch = (cpu == CPU_TYPE_X86) ? @"x86" : @"ppc";
+
+ NSMutableDictionary *archSections;
+
+ if (!sectionData_) {
+ sectionData_ = [[NSMutableDictionary alloc] init];
+ }
+
+ if (![sectionData_ objectForKey:architecture_]) {
+ [sectionData_ setObject:[[NSMutableDictionary alloc] init] forKey:arch];
+ }
+
+ archSections = [sectionData_ objectForKey:arch];
+
+ dwarf2reader::SectionMap* oneArchitectureSectionMap = [self getSectionMapForArchitecture:arch];
// loop through every segment command, then through every section
// contained inside each of them
@@ -459,13 +717,18 @@
uint32_t nsects = SwapLongIfNeeded(seg->nsects);
for (uint32_t j = 0; j < nsects; ++j) {
- //printf("%d: %s %s\n", sectionNumber, seg->segname, sect->sectname );
NSString *segSectName = [NSString stringWithFormat:@"%s%s",
- seg->segname, sect->sectname ];
-
- [sectionNumbers_ setValue:[NSNumber numberWithUnsignedLong:sectionNumber]
- forKey:segSectName ];
+ seg->segname, sect->sectname];
+ [archSections setObject:[[MachSection alloc] initWithMachSection:sect andNumber:sectionNumber]
+ forKey:segSectName];
+
+ // filter out sections with size 0, offset 0
+ if (sect->offset != 0 && sect->size != 0) {
+ // fill sectionmap for dwarf reader
+ oneArchitectureSectionMap->insert(make_pair(sect->sectname,make_pair(((const char*)header) + SwapLongIfNeeded(sect->offset), (size_t)SwapLongIfNeeded(sect->size))));
+ }
+
++sect;
++sectionNumber;
}
@@ -682,11 +945,15 @@
// Sources ordered by address
NSArray *sources = [[sources_ allKeys]
sortedArrayUsingSelector:@selector(compare:)];
+ NSMutableDictionary *fileNameToFileIndex = [[NSMutableDictionary alloc] init];
unsigned int sourceCount = [sources count];
for (unsigned int i = 0; i < sourceCount; ++i) {
NSString *file = [sources_ objectForKey:[sources objectAtIndex:i]];
if (!WriteFormat(fd, "FILE %d %s\n", i + 1, [file UTF8String]))
return NO;
+
+ [fileNameToFileIndex setObject:[NSNumber numberWithUnsignedInt:i+1]
+ forKey:file];
}
// Symbols
@@ -699,6 +966,11 @@
for (unsigned int i = 0; i < addressCount; ++i) {
NSNumber *address = [sortedAddresses objectAtIndex:i];
+ // skip sources that have a starting address of 0
+ if ([address unsignedLongValue] == 0) {
+ continue;
+ }
+
uint64_t addressVal = [address unsignedLongLongValue] - baseAddress;
// Get the next address to calculate the length
@@ -734,7 +1006,7 @@
if ([symbol hasPrefix:@"__static_initialization_and_destruction_0"])
continue;
- if ([symbol hasPrefix:@"_GLOBAL__I__"])
+ if ([symbol hasPrefix:@"_GLOBAL__I_"])
continue;
if ([symbol hasPrefix:@"__func__."])
@@ -790,8 +1062,17 @@
// Source line
uint64_t length = nextAddressVal - addressVal;
+
+ // if fileNameToFileIndex/dict has an entry for the
+ // file/kFunctionFileKey, we're processing DWARF and have stored
+ // files for each program counter. If there is no entry, we're
+ // processing STABS and can use the old method of mapping
+ // addresses to files(which was basically iterating over a set
+ // of addresses until we reached one that was greater than the
+ // high PC of the current file, then moving on to the next file)
+ NSNumber *fileIndex = [fileNameToFileIndex objectForKey:[dict objectForKey:kFunctionFileKey]];
if (!WriteFormat(fd, "%llx %llx %d %d\n", addressVal, length,
- [line unsignedIntValue], fileIdx))
+ [line unsignedIntValue], fileIndex ? [fileIndex unsignedIntValue] : fileIdx))
return NO;
} else {
// PUBLIC <address> <stack-size> <name>
@@ -815,6 +1096,49 @@
sourcePath_ = [path copy];
+ // Test for .DSYM bundle
+ NSBundle *dsymBundle = [NSBundle bundleWithPath:sourcePath_];
+
+ if (dsymBundle) {
+
+ // we need to take the DSYM bundle path and remove it's
+ // extension to get the name of the file inside the resources
+ // directory of the bundle that actually has the DWARF
+ // information
+ // But, Xcode supports something called "Wrapper extension"(see
+ // build settings), which would make the bundle name
+ // /tmp/foo/test.kext.dSYM, but the dwarf binary name would
+ // still be "test". so, now we loop through until deleting the
+ // extension doesn't change the string
+
+ // e.g. suppose sourcepath_ is /tmp/foo/test.dSYM
+
+ NSString *dwarfBinName = [[sourcePath_ lastPathComponent] stringByDeletingPathExtension];
+
+ // now, dwarfBinName is "test"
+
+ while (![[dwarfBinName stringByDeletingPathExtension] isEqualToString:dwarfBinName]) {
+ dwarfBinName = [dwarfBinName stringByDeletingPathExtension];
+ }
+
+ NSString *dwarfBinPath;
+ dwarfBinPath = [dsymBundle pathForResource:dwarfBinName ofType:nil inDirectory:@"DWARF"];
+
+ if (dwarfBinPath == nil) {
+ NSLog(@"The bundle passed on the command line does not appear to be a DWARF dSYM bundle");
+ [self autorelease];
+ return nil;
+ }
+
+ // otherwise we're good to go
+ [sourcePath_ release];
+
+ sourcePath_ = [dwarfBinPath copy];
+ NSLog(@"Loading DWARF dSYM file from %@", sourcePath_);
+ }
+
+ sectionsForArch_ = new ArchSectionMap();
+
if (![self loadModuleInfo]) {
[self autorelease];
return nil;
@@ -858,7 +1182,8 @@
[functionAddresses_ release];
[sources_ release];
[headers_ release];
-
+ delete sectionsForArch_;
+
[super dealloc];
}
@@ -889,7 +1214,7 @@
return NO;
[architecture_ autorelease];
- architecture_ = [architecture copy];
+ architecture_ = [normalized copy];
}
return isValid;
@@ -921,3 +1246,23 @@
}
@end
+
+ implementation MachSection
+
+- (id)initWithMachSection:(section *)sect andNumber:(uint32_t)sectionNumber {
+ if ((self = [super init])) {
+ sect_ = sect;
+ sectionNumber_ = sectionNumber;
+ }
+
+ return self;
+}
+
+- (section*)sectionPointer {
+ return sect_;
+}
+
+- (uint32_t)sectionNumber {
+ return sectionNumber_;
+}
+ end
Added: trunk/google-breakpad/src/common/mac/dwarf/bytereader-inl.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/bytereader-inl.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,141 @@
+// Copyright 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.
+
+#ifndef UTIL_DEBUGINFO_BYTEREADER_INL_H__
+#define UTIL_DEBUGINFO_BYTEREADER_INL_H__
+
+#include "common/mac/dwarf/bytereader.h"
+
+namespace dwarf2reader {
+
+inline uint8 ByteReader::ReadOneByte(const char* buffer) const {
+ return buffer[0];
+}
+
+inline uint16 ByteReader::ReadTwoBytes(const char* buffer) const {
+ const uint16 buffer0 = static_cast<uint16>(buffer[0]);
+ const uint16 buffer1 = static_cast<uint16>(buffer[1]);
+ if (endian_ == ENDIANNESS_LITTLE) {
+ return buffer0 | buffer1 << 8;
+ } else {
+ return buffer1 | buffer0 << 8;
+ }
+}
+
+inline uint64 ByteReader::ReadFourBytes(const char* buffer) const {
+ const uint32 buffer0 = static_cast<uint32>(buffer[0]);
+ const uint32 buffer1 = static_cast<uint32>(buffer[1]);
+ const uint32 buffer2 = static_cast<uint32>(buffer[2]);
+ const uint32 buffer3 = static_cast<uint32>(buffer[3]);
+ if (endian_ == ENDIANNESS_LITTLE) {
+ return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24;
+ } else {
+ return buffer3 | buffer2 << 8 | buffer1 << 16 | buffer0 << 24;
+ }
+}
+
+inline uint64 ByteReader::ReadEightBytes(const char* buffer) const {
+ const uint64 buffer0 = static_cast<uint64>(buffer[0]);
+ const uint64 buffer1 = static_cast<uint64>(buffer[1]);
+ const uint64 buffer2 = static_cast<uint64>(buffer[2]);
+ const uint64 buffer3 = static_cast<uint64>(buffer[3]);
+ const uint64 buffer4 = static_cast<uint64>(buffer[4]);
+ const uint64 buffer5 = static_cast<uint64>(buffer[5]);
+ const uint64 buffer6 = static_cast<uint64>(buffer[6]);
+ const uint64 buffer7 = static_cast<uint64>(buffer[7]);
+ if (endian_ == ENDIANNESS_LITTLE) {
+ return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24 |
+ buffer4 << 32 | buffer5 << 40 | buffer6 << 48 | buffer7 << 56;
+ } else {
+ return buffer7 | buffer6 << 8 | buffer5 << 16 | buffer4 << 24 |
+ buffer3 << 32 | buffer2 << 40 | buffer1 << 48 | buffer0 << 56;
+ }
+}
+
+// Read an unsigned LEB128 number. Each byte contains 7 bits of
+// information, plus one bit saying whether the number continues or
+// not.
+
+inline uint64 ByteReader::ReadUnsignedLEB128(const char* buffer,
+ size_t* len) const {
+ uint64 result = 0;
+ size_t num_read = 0;
+ unsigned int shift = 0;
+ unsigned char byte;
+
+ do {
+ byte = *buffer++;
+ num_read++;
+
+ result |= (static_cast<uint64>(byte & 0x7f)) << shift;
+
+ shift += 7;
+
+ } while (byte & 0x80);
+
+ *len = num_read;
+
+ return result;
+}
+
+// Read a signed LEB128 number. These are like regular LEB128
+// numbers, except the last byte may have a sign bit set.
+
+inline int64 ByteReader::ReadSignedLEB128(const char* buffer,
+ size_t* len) const {
+ int64 result = 0;
+ unsigned int shift = 0;
+ size_t num_read = 0;
+ unsigned char byte;
+
+ do {
+ byte = *buffer++;
+ num_read++;
+ result |= (static_cast<uint64>(byte & 0x7f) << shift);
+ shift += 7;
+ } while (byte & 0x80);
+
+ if ((shift < 8 * sizeof (result)) && (byte & 0x40))
+ result |= -((static_cast<int64>(1)) << shift);
+ *len = num_read;
+ return result;
+}
+
+inline uint64 ByteReader::ReadOffset(const char* buffer) const {
+ assert(this->offset_reader_);
+ return (this->*offset_reader_)(buffer);
+}
+
+inline uint64 ByteReader::ReadAddress(const char* buffer) const {
+ assert(this->address_reader_);
+ return (this->*address_reader_)(buffer);
+}
+
+} // namespace dwarf2reader
+
+#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__
Added: trunk/google-breakpad/src/common/mac/dwarf/bytereader.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/bytereader.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,62 @@
+// Copyright 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.
+
+#include "common/mac/dwarf/bytereader-inl.h"
+
+#include "common/mac/dwarf/bytereader.h"
+
+namespace dwarf2reader {
+
+ByteReader::ByteReader(enum Endianness endian)
+ :offset_reader_(NULL), address_reader_(NULL), endian_(endian),
+ address_size_(0), offset_size_(0)
+{ }
+
+ByteReader::~ByteReader() { }
+
+void ByteReader::SetOffsetSize(uint8 size) {
+ offset_size_ = size;
+ assert(size == 4 || size == 8);
+ if (size == 4) {
+ this->offset_reader_ = &ByteReader::ReadFourBytes;
+ } else {
+ this->offset_reader_ = &ByteReader::ReadEightBytes;
+ }
+}
+
+void ByteReader::SetAddressSize(uint8 size) {
+ address_size_ = size;
+ assert(size == 4 || size == 8);
+ if (size == 4) {
+ this->address_reader_ = &ByteReader::ReadFourBytes;
+ } else {
+ this->address_reader_ = &ByteReader::ReadEightBytes;
+ }
+}
+
+} // namespace dwarf2reader
Added: trunk/google-breakpad/src/common/mac/dwarf/bytereader.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/bytereader.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,132 @@
+// Copyright 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.
+
+#ifndef COMMON_MAC_DWARF_BYTEREADER_H__
+#define COMMON_MAC_DWARF_BYTEREADER_H__
+
+#include <string>
+#include "common/mac/dwarf/types.h"
+
+namespace dwarf2reader {
+
+// We can't use the obvious name of LITTLE_ENDIAN and BIG_ENDIAN
+// because it conflicts with a macro
+enum Endianness {
+ ENDIANNESS_BIG,
+ ENDIANNESS_LITTLE
+};
+
+// Class that knows how to read both big endian and little endian
+// numbers, for use in DWARF2/3 reader.
+// Takes an endianness argument.
+// To read addresses and offsets, SetAddressSize and SetOffsetSize
+// must be called first.
+class ByteReader {
+ public:
+ explicit ByteReader(enum Endianness endian);
+ virtual ~ByteReader();
+
+ // Set the address size to SIZE, which sets up the ReadAddress member
+ // so that it works.
+ void SetAddressSize(uint8 size);
+
+ // Set the offset size to SIZE, which sets up the ReadOffset member
+ // so that it works.
+ void SetOffsetSize(uint8 size);
+
+ // Return the current offset size
+ uint8 OffsetSize() const { return offset_size_; }
+
+ // Return the current address size
+ uint8 AddressSize() const { return address_size_; }
+
+ // Read a single byte from BUFFER and return it as an unsigned 8 bit
+ // number.
+ uint8 ReadOneByte(const char* buffer) const;
+
+ // Read two bytes from BUFFER and return it as an unsigned 16 bit
+ // number.
+ uint16 ReadTwoBytes(const char* buffer) const;
+
+ // Read four bytes from BUFFER and return it as an unsigned 32 bit
+ // number. This function returns a uint64 so that it is compatible
+ // with ReadAddress and ReadOffset. The number it returns will
+ // never be outside the range of an unsigned 32 bit integer.
+ uint64 ReadFourBytes(const char* buffer) const;
+
+ // Read eight bytes from BUFFER and return it as an unsigned 64 bit
+ // number
+ uint64 ReadEightBytes(const char* buffer) const;
+
+ // Read an unsigned LEB128 (Little Endian Base 128) number from
+ // BUFFER and return it as an unsigned 64 bit integer. LEN is set
+ // to the length read. Everybody seems to reinvent LEB128 as a
+ // variable size integer encoding, DWARF has had it for a long time.
+ uint64 ReadUnsignedLEB128(const char* buffer, size_t* len) const;
+
+ // Read a signed LEB128 number from BUFFER and return it as an
+ // signed 64 bit integer. LEN is set to the length read.
+ int64 ReadSignedLEB128(const char* buffer, size_t* len) const;
+
+ // Read an offset from BUFFER and return it as an unsigned 64 bit
+ // integer. DWARF2/3 define offsets as either 4 or 8 bytes,
+ // generally depending on the amount of DWARF2/3 info present.
+ uint64 ReadOffset(const char* buffer) const;
+
+ // Read an address from BUFFER and return it as an unsigned 64 bit
+ // integer. DWARF2/3 allow addresses to be any size from 0-255
+ // bytes currently. Internally we support 4 and 8 byte addresses,
+ // and will CHECK on anything else.
+ uint64 ReadAddress(const char* buffer) const;
+
+ private:
+
+ // Function pointer type for our address and offset readers.
+ typedef uint64 (ByteReader::*AddressReader)(const char*) const;
+
+ // Read an offset from BUFFER and return it as an unsigned 64 bit
+ // integer. DWARF2/3 define offsets as either 4 or 8 bytes,
+ // generally depending on the amount of DWARF2/3 info present.
+ // This function pointer gets set by SetOffsetSize.
+ AddressReader offset_reader_;
+
+ // Read an address from BUFFER and return it as an unsigned 64 bit
+ // integer. DWARF2/3 allow addresses to be any size from 0-255
+ // bytes currently. Internally we support 4 and 8 byte addresses,
+ // and will CHECK on anything else.
+ // This function pointer gets set by SetAddressSize.
+ AddressReader address_reader_;
+
+ Endianness endian_;
+ uint8 address_size_;
+ uint8 offset_size_;
+};
+
+} // namespace dwarf2reader
+
+#endif // COMMON_MAC_DWARF_BYTEREADER_H__
Added: trunk/google-breakpad/src/common/mac/dwarf/dwarf2enums.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/dwarf2enums.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,490 @@
+// Copyright 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.
+
+#ifndef COMMON_MAC_DWARF_DWARF2ENUMS_H__
+#define COMMON_MAC_DWARF_DWARF2ENUMS_H__
+
+namespace dwarf2reader {
+
+// These enums do not follow the google3 style only because they are
+// known universally (specs, other implementations) by the names in
+// exactly this capitalization.
+// Tag names and codes.
+enum DwarfTag {
+ DW_TAG_padding = 0x00,
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_param = 0x2f,
+ DW_TAG_template_value_param = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ // DWARF 3.
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ // SGI/MIPS Extensions.
+ DW_TAG_MIPS_loop = 0x4081,
+ // HP extensions. See:
+ // ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz
+ DW_TAG_HP_array_descriptor = 0x4090,
+ // GNU extensions.
+ DW_TAG_format_label = 0x4101, // For FORTRAN 77 and Fortran 90.
+ DW_TAG_function_template = 0x4102, // For C++.
+ DW_TAG_class_template = 0x4103, // For C++.
+ DW_TAG_GNU_BINCL = 0x4104,
+ DW_TAG_GNU_EINCL = 0x4105,
+ // Extensions for UPC. See: http://upc.gwu.edu/~upc.
+ DW_TAG_upc_shared_type = 0x8765,
+ DW_TAG_upc_strict_type = 0x8766,
+ DW_TAG_upc_relaxed_type = 0x8767,
+ // PGI (STMicroelectronics) extensions. No documentation available.
+ DW_TAG_PGI_kanji_type = 0xA000,
+ DW_TAG_PGI_interface_block = 0xA020
+};
+
+
+enum DwarfHasChild {
+ DW_children_no = 0,
+ DW_children_yes = 1
+};
+
+// Form names and codes.
+enum DwarfForm {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16
+};
+
+// Attribute names and codes
+enum DwarfAttribute {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_subscr_data = 0x0a,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_element_list = 0x0f,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_member = 0x14,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_stride_size = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_items = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ // DWARF 3 values.
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ // SGI/MIPS extensions.
+ DW_AT_MIPS_fde = 0x2001,
+ DW_AT_MIPS_loop_begin = 0x2002,
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
+ DW_AT_MIPS_epilog_begin = 0x2004,
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
+ DW_AT_MIPS_linkage_name = 0x2007,
+ DW_AT_MIPS_stride = 0x2008,
+ DW_AT_MIPS_abstract_name = 0x2009,
+ DW_AT_MIPS_clone_origin = 0x200a,
+ DW_AT_MIPS_has_inlines = 0x200b,
+ // HP extensions.
+ DW_AT_HP_block_index = 0x2000,
+ DW_AT_HP_unmodifiable = 0x2001, // Same as DW_AT_MIPS_fde.
+ DW_AT_HP_actuals_stmt_list = 0x2010,
+ DW_AT_HP_proc_per_section = 0x2011,
+ DW_AT_HP_raw_data_ptr = 0x2012,
+ DW_AT_HP_pass_by_reference = 0x2013,
+ DW_AT_HP_opt_level = 0x2014,
+ DW_AT_HP_prof_version_id = 0x2015,
+ DW_AT_HP_opt_flags = 0x2016,
+ DW_AT_HP_cold_region_low_pc = 0x2017,
+ DW_AT_HP_cold_region_high_pc = 0x2018,
+ DW_AT_HP_all_variables_modifiable = 0x2019,
+ DW_AT_HP_linkage_name = 0x201a,
+ DW_AT_HP_prof_flags = 0x201b, // In comp unit of procs_info for -g.
+ // GNU extensions.
+ DW_AT_sf_names = 0x2101,
+ DW_AT_src_info = 0x2102,
+ DW_AT_mac_info = 0x2103,
+ DW_AT_src_coords = 0x2104,
+ DW_AT_body_begin = 0x2105,
+ DW_AT_body_end = 0x2106,
+ DW_AT_GNU_vector = 0x2107,
+ // VMS extensions.
+ DW_AT_VMS_rtnbeg_pd_address = 0x2201,
+ // UPC extension.
+ DW_AT_upc_threads_scaled = 0x3210,
+ // PGI (STMicroelectronics) extensions.
+ DW_AT_PGI_lbase = 0x3a00,
+ DW_AT_PGI_soffset = 0x3a01,
+ DW_AT_PGI_lstride = 0x3a02
+};
+
+
+// Line number opcodes.
+enum DwarfLineNumberOps {
+ DW_LNS_extended_op = 0,
+ DW_LNS_copy = 1,
+ DW_LNS_advance_pc = 2,
+ DW_LNS_advance_line = 3,
+ DW_LNS_set_file = 4,
+ DW_LNS_set_column = 5,
+ DW_LNS_negate_stmt = 6,
+ DW_LNS_set_basic_block = 7,
+ DW_LNS_const_add_pc = 8,
+ DW_LNS_fixed_advance_pc = 9,
+ // DWARF 3.
+ DW_LNS_set_prologue_end = 10,
+ DW_LNS_set_epilogue_begin = 11,
+ DW_LNS_set_isa = 12
+};
+
+// Line number extended opcodes.
+enum DwarfLineNumberExtendedOps {
+ DW_LNE_end_sequence = 1,
+ DW_LNE_set_address = 2,
+ DW_LNE_define_file = 3,
+ // HP extensions.
+ DW_LNE_HP_negate_is_UV_update = 0x11,
+ DW_LNE_HP_push_context = 0x12,
+ DW_LNE_HP_pop_context = 0x13,
+ DW_LNE_HP_set_file_line_column = 0x14,
+ DW_LNE_HP_set_routine_name = 0x15,
+ DW_LNE_HP_set_sequence = 0x16,
+ DW_LNE_HP_negate_post_semantics = 0x17,
+ DW_LNE_HP_negate_function_exit = 0x18,
+ DW_LNE_HP_negate_front_end_logical = 0x19,
+ DW_LNE_HP_define_proc = 0x20
+};
+
+// Type encoding names and codes
+enum DwarfEncoding {
+ DW_ATE_address =0x1,
+ DW_ATE_boolean =0x2,
+ DW_ATE_complex_float =0x3,
+ DW_ATE_float =0x4,
+ DW_ATE_signed =0x5,
+ DW_ATE_signed_char =0x6,
+ DW_ATE_unsigned =0x7,
+ DW_ATE_unsigned_char =0x8,
+ // DWARF3/DWARF3f
+ DW_ATE_imaginary_float =0x9,
+ DW_ATE_packed_decimal =0xa,
+ DW_ATE_numeric_string =0xb,
+ DW_ATE_edited =0xc,
+ DW_ATE_signed_fixed =0xd,
+ DW_ATE_unsigned_fixed =0xe,
+ DW_ATE_decimal_float =0xf,
+ DW_ATE_lo_user =0x80,
+ DW_ATE_hi_user =0xff
+};
+
+// Location virtual machine opcodes
+enum DwarfOpcode {
+ DW_OP_addr =0x03,
+ DW_OP_deref =0x06,
+ DW_OP_const1u =0x08,
+ DW_OP_const1s =0x09,
+ DW_OP_const2u =0x0a,
+ DW_OP_const2s =0x0b,
+ DW_OP_const4u =0x0c,
+ DW_OP_const4s =0x0d,
+ DW_OP_const8u =0x0e,
+ DW_OP_const8s =0x0f,
+ DW_OP_constu =0x10,
+ DW_OP_consts =0x11,
+ DW_OP_dup =0x12,
+ DW_OP_drop =0x13,
+ DW_OP_over =0x14,
+ DW_OP_pick =0x15,
+ DW_OP_swap =0x16,
+ DW_OP_rot =0x17,
+ DW_OP_xderef =0x18,
+ DW_OP_abs =0x19,
+ DW_OP_and =0x1a,
+ DW_OP_div =0x1b,
+ DW_OP_minus =0x1c,
+ DW_OP_mod =0x1d,
+ DW_OP_mul =0x1e,
+ DW_OP_neg =0x1f,
+ DW_OP_not =0x20,
+ DW_OP_or =0x21,
+ DW_OP_plus =0x22,
+ DW_OP_plus_uconst =0x23,
+ DW_OP_shl =0x24,
+ DW_OP_shr =0x25,
+ DW_OP_shra =0x26,
+ DW_OP_xor =0x27,
+ DW_OP_bra =0x28,
+ DW_OP_eq =0x29,
+ DW_OP_ge =0x2a,
+ DW_OP_gt =0x2b,
+ DW_OP_le =0x2c,
+ DW_OP_lt =0x2d,
+ DW_OP_ne =0x2e,
+ DW_OP_skip =0x2f,
+ DW_OP_lit0 =0x30,
+ DW_OP_lit1 =0x31,
+ DW_OP_lit2 =0x32,
+ DW_OP_lit3 =0x33,
+ DW_OP_lit4 =0x34,
+ DW_OP_lit5 =0x35,
+ DW_OP_lit6 =0x36,
+ DW_OP_lit7 =0x37,
+ DW_OP_lit8 =0x38,
+ DW_OP_lit9 =0x39,
+ DW_OP_lit10 =0x3a,
+ DW_OP_lit11 =0x3b,
+ DW_OP_lit12 =0x3c,
+ DW_OP_lit13 =0x3d,
+ DW_OP_lit14 =0x3e,
+ DW_OP_lit15 =0x3f,
+ DW_OP_lit16 =0x40,
+ DW_OP_lit17 =0x41,
+ DW_OP_lit18 =0x42,
+ DW_OP_lit19 =0x43,
+ DW_OP_lit20 =0x44,
+ DW_OP_lit21 =0x45,
+ DW_OP_lit22 =0x46,
+ DW_OP_lit23 =0x47,
+ DW_OP_lit24 =0x48,
+ DW_OP_lit25 =0x49,
+ DW_OP_lit26 =0x4a,
+ DW_OP_lit27 =0x4b,
+ DW_OP_lit28 =0x4c,
+ DW_OP_lit29 =0x4d,
+ DW_OP_lit30 =0x4e,
+ DW_OP_lit31 =0x4f,
+ DW_OP_reg0 =0x50,
+ DW_OP_reg1 =0x51,
+ DW_OP_reg2 =0x52,
+ DW_OP_reg3 =0x53,
+ DW_OP_reg4 =0x54,
+ DW_OP_reg5 =0x55,
+ DW_OP_reg6 =0x56,
+ DW_OP_reg7 =0x57,
+ DW_OP_reg8 =0x58,
+ DW_OP_reg9 =0x59,
+ DW_OP_reg10 =0x5a,
+ DW_OP_reg11 =0x5b,
+ DW_OP_reg12 =0x5c,
+ DW_OP_reg13 =0x5d,
+ DW_OP_reg14 =0x5e,
+ DW_OP_reg15 =0x5f,
+ DW_OP_reg16 =0x60,
+ DW_OP_reg17 =0x61,
+ DW_OP_reg18 =0x62,
+ DW_OP_reg19 =0x63,
+ DW_OP_reg20 =0x64,
+ DW_OP_reg21 =0x65,
+ DW_OP_reg22 =0x66,
+ DW_OP_reg23 =0x67,
+ DW_OP_reg24 =0x68,
+ DW_OP_reg25 =0x69,
+ DW_OP_reg26 =0x6a,
+ DW_OP_reg27 =0x6b,
+ DW_OP_reg28 =0x6c,
+ DW_OP_reg29 =0x6d,
+ DW_OP_reg30 =0x6e,
+ DW_OP_reg31 =0x6f,
+ DW_OP_breg0 =0x70,
+ DW_OP_breg1 =0x71,
+ DW_OP_breg2 =0x72,
+ DW_OP_breg3 =0x73,
+ DW_OP_breg4 =0x74,
+ DW_OP_breg5 =0x75,
+ DW_OP_breg6 =0x76,
+ DW_OP_breg7 =0x77,
+ DW_OP_breg8 =0x78,
+ DW_OP_breg9 =0x79,
+ DW_OP_breg10 =0x7a,
+ DW_OP_breg11 =0x7b,
+ DW_OP_breg12 =0x7c,
+ DW_OP_breg13 =0x7d,
+ DW_OP_breg14 =0x7e,
+ DW_OP_breg15 =0x7f,
+ DW_OP_breg16 =0x80,
+ DW_OP_breg17 =0x81,
+ DW_OP_breg18 =0x82,
+ DW_OP_breg19 =0x83,
+ DW_OP_breg20 =0x84,
+ DW_OP_breg21 =0x85,
+ DW_OP_breg22 =0x86,
+ DW_OP_breg23 =0x87,
+ DW_OP_breg24 =0x88,
+ DW_OP_breg25 =0x89,
+ DW_OP_breg26 =0x8a,
+ DW_OP_breg27 =0x8b,
+ DW_OP_breg28 =0x8c,
+ DW_OP_breg29 =0x8d,
+ DW_OP_breg30 =0x8e,
+ DW_OP_breg31 =0x8f,
+ DW_OP_regX =0x90,
+ DW_OP_fbreg =0x91,
+ DW_OP_bregX =0x92,
+ DW_OP_piece =0x93,
+ DW_OP_deref_size =0x94,
+ DW_OP_xderef_size =0x95,
+ DW_OP_nop =0x96,
+ // DWARF3/DWARF3f
+ DW_OP_push_object_address =0x97,
+ DW_OP_call2 =0x98,
+ DW_OP_call4 =0x99,
+ DW_OP_call_ref =0x9a,
+ DW_OP_form_tls_address =0x9b,
+ DW_OP_call_frame_cfa =0x9c,
+ DW_OP_bit_piece =0x9d,
+ DW_OP_lo_user =0xe0,
+ DW_OP_hi_user =0xff,
+ // GNU extensions
+ DW_OP_GNU_push_tls_address =0xe0
+};
+
+} // namespace dwarf2reader
+#endif // COMMON_MAC_DWARF_DWARF2ENUMS_H__
Added: trunk/google-breakpad/src/common/mac/dwarf/dwarf2reader.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/dwarf2reader.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,830 @@
+// Copyright 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.
+
+#include <ext/hash_map>
+#include <stack>
+#include <utility>
+
+#include "common/mac/dwarf/bytereader-inl.h"
+#include "common/mac/dwarf/dwarf2reader.h"
+#include "common/mac/dwarf/bytereader.h"
+#include "common/mac/dwarf/line_state_machine.h"
+
+namespace __gnu_cxx
+{
+ template<> struct hash< std::string >
+ {
+ size_t operator()( const std::string& x ) const
+ {
+ return hash< const char* >()( x.c_str() );
+ }
+ };
+}
+
+namespace dwarf2reader {
+
+// Read a DWARF2/3 initial length field from START, using READER, and
+// report the length in LEN. Return the actual initial length.
+
+static uint64 ReadInitialLength(const char* start,
+ ByteReader* reader, size_t* len) {
+ const uint64 initial_length = reader->ReadFourBytes(start);
+ start += 4;
+
+ // In DWARF2/3, if the initial length is all 1 bits, then the offset
+ // size is 8 and we need to read the next 8 bytes for the real length.
+ if (initial_length == 0xffffffff) {
+ reader->SetOffsetSize(8);
+ *len = 12;
+ return reader->ReadOffset(start);
+ } else {
+ reader->SetOffsetSize(4);
+ *len = 4;
+ }
+ return initial_length;
+}
+
+CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset,
+ ByteReader* reader, Dwarf2Handler* handler)
+ : offset_from_section_start_(offset), reader_(reader),
+ sections_(sections), handler_(handler), abbrevs_(NULL),
+ string_buffer_(NULL), string_buffer_length_(0) {}
+
+// Read a DWARF2/3 abbreviation section.
+// Each abbrev consists of a abbreviation number, a tag, a byte
+// specifying whether the tag has children, and a list of
+// attribute/form pairs.
+// The list of forms is terminated by a 0 for the attribute, and a
+// zero for the form. The entire abbreviation section is terminated
+// by a zero for the code.
+
+void CompilationUnit::ReadAbbrevs() {
+ if (abbrevs_)
+ return;
+
+ // First get the debug_abbrev section
+ SectionMap::const_iterator iter = sections_.find("__debug_abbrev");
+ assert(iter != sections_.end());
+
+ abbrevs_ = new vector<Abbrev>;
+ abbrevs_->resize(1);
+
+ // The only way to check whether we are reading over the end of the
+ // buffer would be to first compute the size of the leb128 data by
+ // reading it, then go back and read it again.
+ const char* abbrev_start = iter->second.first +
+ header_.abbrev_offset;
+ const char* abbrevptr = abbrev_start;
+ const uint64 abbrev_length = iter->second.second - header_.abbrev_offset;
+
+ while (1) {
+ CompilationUnit::Abbrev abbrev;
+ size_t len;
+ const uint32 number = reader_->ReadUnsignedLEB128(abbrevptr, &len);
+
+ if (number == 0)
+ break;
+ abbrev.number = number;
+ abbrevptr += len;
+
+ assert(abbrevptr < abbrev_start + abbrev_length);
+ const uint32 tag = reader_->ReadUnsignedLEB128(abbrevptr, &len);
+ abbrevptr += len;
+ abbrev.tag = static_cast<enum DwarfTag>(tag);
+
+ assert(abbrevptr < abbrev_start + abbrev_length);
+ abbrev.has_children = reader_->ReadOneByte(abbrevptr);
+ abbrevptr += 1;
+
+ assert(abbrevptr < abbrev_start + abbrev_length);
+
+ while (1) {
+ const uint32 nametemp = reader_->ReadUnsignedLEB128(abbrevptr, &len);
+ abbrevptr += len;
+
+ assert(abbrevptr < abbrev_start + abbrev_length);
+ const uint32 formtemp = reader_->ReadUnsignedLEB128(abbrevptr, &len);
+ abbrevptr += len;
+ if (nametemp == 0 && formtemp == 0)
+ break;
+
+ const enum DwarfAttribute name =
+ static_cast<enum DwarfAttribute>(nametemp);
+ const enum DwarfForm form = static_cast<enum DwarfForm>(formtemp);
+ abbrev.attributes.push_back(make_pair(name, form));
+ }
+ assert(abbrev.number == abbrevs_->size());
+ abbrevs_->push_back(abbrev);
+ }
+}
+
+// Skips a single DIE's attributes.
+const char* CompilationUnit::SkipDIE(const char* start,
+ const Abbrev& abbrev) {
+ for (AttributeList::const_iterator i = abbrev.attributes.begin();
+ i != abbrev.attributes.end();
+ i++) {
+ start = SkipAttribute(start, i->second);
+ }
+ return start;
+}
+
+// Skips a single attribute form's data.
+const char* CompilationUnit::SkipAttribute(const char* start,
+ enum DwarfForm form) {
+ size_t len;
+
+ switch (form) {
+ case DW_FORM_indirect:
+ form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
+ &len));
+ start += len;
+ return SkipAttribute(start, form);
+ break;
+
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ return start + 1;
+ break;
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ return start + 2;
+ break;
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ return start + 4;
+ break;
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ return start + 8;
+ break;
+ case DW_FORM_string:
+ return start + strlen(start) + 1;
+ break;
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ break;
+
+ case DW_FORM_sdata:
+ reader_->ReadSignedLEB128(start, &len);
+ return start + len;
+ break;
+ case DW_FORM_addr:
+ return start + reader_->AddressSize();
+ break;
+ case DW_FORM_ref_addr:
+ // DWARF2 and 3 differ on whether ref_addr is address size or
+ // offset size.
+ assert(header_.version == 2 || header_.version == 3);
+ if (header_.version == 2) {
+ return start + reader_->AddressSize();
+ } else if (header_.version == 3) {
+ return start + reader_->OffsetSize();
+ }
+ break;
+
+ case DW_FORM_block1:
+ return start + 1 + reader_->ReadOneByte(start);
+ break;
+ case DW_FORM_block2:
+ return start + 2 + reader_->ReadTwoBytes(start);
+ break;
+ case DW_FORM_block4:
+ return start + 4 + reader_->ReadFourBytes(start);
+ break;
+ case DW_FORM_block: {
+ uint64 size = reader_->ReadUnsignedLEB128(start, &len);
+ return start + size + len;
+ }
+ break;
+ case DW_FORM_strp:
+ return start + reader_->OffsetSize();
+ break;
+ default:
+ fprintf(stderr,"Unhandled form type");
+ }
+ fprintf(stderr,"Unhandled form type");
+ return NULL;
+}
+
+// Read a DWARF2/3 header.
+// The header is variable length in DWARF3 (and DWARF2 as extended by
+// most compilers), and consists of an length field, a version number,
+// the offset in the .debug_abbrev section for our abbrevs, and an
+// address size.
+void CompilationUnit::ReadHeader() {
+ const char* headerptr = buffer_;
+ size_t initial_length_size;
+
+ assert(headerptr + 4 < buffer_ + buffer_length_);
+ const uint64 initial_length = ReadInitialLength(headerptr, reader_,
+ &initial_length_size);
+ headerptr += initial_length_size;
+ header_.length = initial_length;
+
+ assert(headerptr + 2 < buffer_ + buffer_length_);
+ header_.version = reader_->ReadTwoBytes(headerptr);
+ headerptr += 2;
+
+ assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_);
+ header_.abbrev_offset = reader_->ReadOffset(headerptr);
+ headerptr += reader_->OffsetSize();
+
+ assert(headerptr + 1 < buffer_ + buffer_length_);
+ header_.address_size = reader_->ReadOneByte(headerptr);
+ reader_->SetAddressSize(header_.address_size);
+ headerptr += 1;
+
+ after_header_ = headerptr;
+
+ // This check ensures that we don't have to do checking during the
+ // reading of DIEs. header_.length does not include the size of the
+ // initial length.
+ assert(buffer_ + initial_length_size + header_.length <=
+ buffer_ + buffer_length_);
+}
+
+uint64 CompilationUnit::Start() {
+ // First get the debug_info section
+ SectionMap::const_iterator iter = sections_.find("__debug_info");
+ assert(iter != sections_.end());
+
+ // Set up our buffer
+ buffer_ = iter->second.first + offset_from_section_start_;
+ buffer_length_ = iter->second.second - offset_from_section_start_;
+
+ // Read the header
+ ReadHeader();
+
+ // Figure out the real length from the end of the initial length to
+ // the end of the compilation unit, since that is the value we
+ // return.
+ uint64 ourlength = header_.length;
+ if (reader_->OffsetSize() == 8)
+ ourlength += 12;
+ else
+ ourlength += 4;
+
+ // See if the user wants this compilation unit, and if not, just return.
+ if (!handler_->StartCompilationUnit(offset_from_section_start_,
+ reader_->AddressSize(),
+ reader_->OffsetSize(),
+ header_.length,
+ header_.version))
+ return ourlength;
+
+ // Otherwise, continue by reading our abbreviation entries.
+ ReadAbbrevs();
+
+ // Set the string section if we have one.
+ iter = sections_.find("__debug_str");
+ if (iter != sections_.end()) {
+ string_buffer_ = iter->second.first;
+ string_buffer_length_ = iter->second.second;
+ }
+
+ // Now that we have our abbreviations, start processing DIE's.
+ ProcessDIEs();
+
+ return ourlength;
+}
+
+// If one really wanted, you could merge SkipAttribute and
+// ProcessAttribute
+// This is all boring data manipulation and calling of the handler.
+const char* CompilationUnit::ProcessAttribute(
+ uint64 dieoffset, const char* start, enum DwarfAttribute attr,
+ enum DwarfForm form) {
+ size_t len;
+
+ switch (form) {
+ // DW_FORM_indirect is never used because it is such a space
+ // waster.
+ case DW_FORM_indirect:
+ form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
+ &len));
+ start += len;
+ return ProcessAttribute(dieoffset, start, attr, form);
+ break;
+
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadOneByte(start));
+ return start + 1;
+ break;
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadTwoBytes(start));
+ return start + 2;
+ break;
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadFourBytes(start));
+ return start + 4;
+ break;
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadEightBytes(start));
+ return start + 8;
+ break;
+ case DW_FORM_string: {
+ const char* str = start;
+ handler_->ProcessAttributeString(dieoffset, attr, form,
+ str);
+ return start + strlen(str) + 1;
+ }
+ break;
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadUnsignedLEB128(start,
+ &len));
+ return start + len;
+ break;
+
+ case DW_FORM_sdata:
+ handler_->ProcessAttributeSigned(dieoffset, attr, form,
+ reader_->ReadSignedLEB128(start, &len));
+ return start + len;
+ break;
+ case DW_FORM_addr:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadAddress(start));
+ return start + reader_->AddressSize();
+ break;
+ case DW_FORM_ref_addr:
+ // DWARF2 and 3 differ on whether ref_addr is address size or
+ // offset size.
+ assert(header_.version == 2 || header_.version == 3);
+ if (header_.version == 2) {
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadAddress(start));
+ return start + reader_->AddressSize();
+ } else if (header_.version == 3) {
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadOffset(start));
+ return start + reader_->OffsetSize();
+ }
+ break;
+
+ case DW_FORM_block1: {
+ uint64 datalen = reader_->ReadOneByte(start);
+ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 1,
+ datalen);
+ return start + 1 + datalen;
+ }
+ break;
+ case DW_FORM_block2: {
+ uint64 datalen = reader_->ReadTwoBytes(start);
+ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 2,
+ datalen);
+ return start + 2 + datalen;
+ }
+ break;
+ case DW_FORM_block4: {
+ uint64 datalen = reader_->ReadFourBytes(start);
+ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 4,
+ datalen);
+ return start + 4 + datalen;
+ }
+ break;
+ case DW_FORM_block: {
+ uint64 datalen = reader_->ReadUnsignedLEB128(start, &len);
+ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len,
+ datalen);
+ return start + datalen + len;
+ }
+ break;
+ case DW_FORM_strp: {
+ assert(string_buffer_ != NULL);
+
+ const uint64 offset = reader_->ReadOffset(start);
+ assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_);
+
+ const char* str = string_buffer_ + offset;
+ handler_->ProcessAttributeString(dieoffset, attr, form,
+ str);
+ return start + reader_->OffsetSize();
+ }
+ break;
+ default:
+ fprintf(stderr, "Unhandled form type");
+ }
+ fprintf(stderr, "Unhandled form type");
+ return NULL;
+}
+
+const char* CompilationUnit::ProcessDIE(uint64 dieoffset,
+ const char* start,
+ const Abbrev& abbrev) {
+ for (AttributeList::const_iterator i = abbrev.attributes.begin();
+ i != abbrev.attributes.end();
+ i++) {
+ start = ProcessAttribute(dieoffset, start, i->first, i->second);
+ }
+ return start;
+}
+
+void CompilationUnit::ProcessDIEs() {
+ const char* dieptr = after_header_;
+ size_t len;
+
+ // lengthstart is the place the length field is based on.
+ // It is the point in the header after the initial length field
+ const char* lengthstart = buffer_;
+
+ // In 64 bit dwarf, the initial length is 12 bytes, because of the
+ // 0xffffffff at the start.
+ if (reader_->OffsetSize() == 8)
+ lengthstart += 12;
+ else
+ lengthstart += 4;
+
+ // we need semantics of boost scoped_ptr here - no intention of trasnferring
+ // ownership of the stack. use const, but then we limit ourselves to not
+ // ever being able to call .reset() on the smart pointer.
+ auto_ptr<stack<uint64> > const die_stack(new stack<uint64>);
+
+ while (dieptr < (lengthstart + header_.length)) {
+ // We give the user the absolute offset from the beginning of
+ // debug_info, since they need it to deal with ref_addr forms.
+ uint64 absolute_offset = (dieptr - buffer_) + offset_from_section_start_;
+
+ uint64 abbrev_num = reader_->ReadUnsignedLEB128(dieptr, &len);
+
+ dieptr += len;
+
+ // Abbrev == 0 represents the end of a list of children.
+ if (abbrev_num == 0) {
+ const uint64 offset = die_stack->top();
+ die_stack->pop();
+ handler_->EndDIE(offset);
+ continue;
+ }
+
+ const Abbrev& abbrev = abbrevs_->at(abbrev_num);
+ const enum DwarfTag tag = abbrev.tag;
+ if (!handler_->StartDIE(absolute_offset, tag, abbrev.attributes)) {
+ dieptr = SkipDIE(dieptr, abbrev);
+ } else {
+ dieptr = ProcessDIE(absolute_offset, dieptr, abbrev);
+ }
+
+ if (abbrev.has_children) {
+ die_stack->push(absolute_offset);
+ } else {
+ handler_->EndDIE(absolute_offset);
+ }
+ }
+}
+
+LineInfo::LineInfo(const char* buffer, uint64 buffer_length,
+ ByteReader* reader, LineInfoHandler* handler):
+ handler_(handler), reader_(reader), buffer_(buffer),
+ buffer_length_(buffer_length) {
+ header_.std_opcode_lengths = NULL;
+}
+
+uint64 LineInfo::Start() {
+ ReadHeader();
+ ReadLines();
+ return after_header_ - buffer_;
+}
+
+// The header for a debug_line section is mildly complicated, because
+// the line info is very tightly encoded.
+void LineInfo::ReadHeader() {
+ const char* lineptr = buffer_;
+ size_t initial_length_size;
+
+ const uint64 initial_length = ReadInitialLength(lineptr, reader_,
+ &initial_length_size);
+
+ lineptr += initial_length_size;
+ header_.total_length = initial_length;
+ assert(buffer_ + initial_length_size + header_.total_length <=
+ buffer_ + buffer_length_);
+
+ // Address size *must* be set by CU ahead of time.
+ assert(reader_->AddressSize() != 0);
+
+ header_.version = reader_->ReadTwoBytes(lineptr);
+ lineptr += 2;
+
+ header_.prologue_length = reader_->ReadOffset(lineptr);
+ lineptr += reader_->OffsetSize();
+
+ header_.min_insn_length = reader_->ReadOneByte(lineptr);
+ lineptr += 1;
+
+ header_.default_is_stmt = reader_->ReadOneByte(lineptr);
+ lineptr += 1;
+
+ header_.line_base = *reinterpret_cast<const int8*>(lineptr);
+ lineptr += 1;
+
+ header_.line_range = reader_->ReadOneByte(lineptr);
+ lineptr += 1;
+
+ header_.opcode_base = reader_->ReadOneByte(lineptr);
+ lineptr += 1;
+
+ header_.std_opcode_lengths = new vector<unsigned char>;
+ header_.std_opcode_lengths->resize(header_.opcode_base + 1);
+ (*header_.std_opcode_lengths)[0] = 0;
+ for (int i = 1; i < header_.opcode_base; i++) {
+ (*header_.std_opcode_lengths)[i] = reader_->ReadOneByte(lineptr);
+ lineptr += 1;
+ }
+
+ // It is legal for the directory entry table to be empty.
+ if (*lineptr) {
+ uint32 dirindex = 1;
+ while (*lineptr) {
+ const char* dirname = lineptr;
+ handler_->DefineDir(dirname, dirindex);
+ lineptr += strlen(dirname) + 1;
+ dirindex++;
+ }
+ }
+ lineptr++;
+
+ // It is also legal for the file entry table to be empty.
+ if (*lineptr) {
+ uint32 fileindex = 1;
+ size_t len;
+ while (*lineptr) {
+ const char* filename = lineptr;
+ lineptr += strlen(filename) + 1;
+
+ uint64 dirindex = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+
+ uint64 mod_time = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+
+ uint64 filelength = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+ handler_->DefineFile(filename, fileindex, dirindex, mod_time,
+ filelength);
+ fileindex++;
+ }
+ }
+ lineptr++;
+
+ after_header_ = lineptr;
+}
+
+/* static */
+bool LineInfo::ProcessOneOpcode(ByteReader* reader,
+ LineInfoHandler* handler,
+ const struct LineInfoHeader &header,
+ const char* start,
+ struct LineStateMachine* lsm,
+ size_t* len,
+ uintptr_t pc,
+ bool *lsm_passes_pc) {
+ size_t oplen = 0;
+ size_t templen;
+ uint8 opcode = reader->ReadOneByte(start);
+ oplen++;
+ start++;
+
+ // If the opcode is great than the opcode_base, it is a special
+ // opcode. Most line programs consist mainly of special opcodes.
+ if (opcode >= header.opcode_base) {
+ opcode -= header.opcode_base;
+ const int64 advance_address = (opcode / header.line_range)
+ * header.min_insn_length;
+ const int64 advance_line = (opcode % header.line_range)
+ + header.line_base;
+
+ // Check if the lsm passes "pc". If so, mark it as passed.
+ if (lsm_passes_pc &&
+ lsm->address <= pc && pc < lsm->address + advance_address) {
+ *lsm_passes_pc = true;
+ }
+
+ lsm->address += advance_address;
+ lsm->line_num += advance_line;
+ lsm->basic_block = true;
+ *len = oplen;
+ return true;
+ }
+
+ // Otherwise, we have the regular opcodes
+ switch (opcode) {
+ case DW_LNS_copy: {
+ lsm->basic_block = false;
+ *len = oplen;
+ return true;
+ }
+
+ case DW_LNS_advance_pc: {
+ uint64 advance_address = reader->ReadUnsignedLEB128(start, &templen);
+ oplen += templen;
+
+ // Check if the lsm passes "pc". If so, mark it as passed.
+ if (lsm_passes_pc && lsm->address <= pc &&
+ pc < lsm->address + header.min_insn_length * advance_address) {
+ *lsm_passes_pc = true;
+ }
+
+ lsm->address += header.min_insn_length * advance_address;
+ }
+ break;
+ case DW_LNS_advance_line: {
+ const int64 advance_line = reader->ReadSignedLEB128(start, &templen);
+ oplen += templen;
+ lsm->line_num += advance_line;
+
+ // With gcc 4.2.1, we can get the line_no here for the first time
+ // since DW_LNS_advance_line is called after DW_LNE_set_address is
+ // called. So we check if the lsm passes "pc" here, not in
+ // DW_LNE_set_address.
+ if (lsm_passes_pc && lsm->address == pc) {
+ *lsm_passes_pc = true;
+ }
+ }
+ break;
+ case DW_LNS_set_file: {
+ const uint64 fileno = reader->ReadUnsignedLEB128(start, &templen);
+ oplen += templen;
+ lsm->file_num = fileno;
+ }
+ break;
+ case DW_LNS_set_column: {
+ const uint64 colno = reader->ReadUnsignedLEB128(start, &templen);
+ oplen += templen;
+ lsm->column_num = colno;
+ }
+ break;
+ case DW_LNS_negate_stmt: {
+ lsm->is_stmt = !lsm->is_stmt;
+ }
+ break;
+ case DW_LNS_set_basic_block: {
+ lsm->basic_block = true;
+ }
+ break;
+ case DW_LNS_fixed_advance_pc: {
+ const uint16 advance_address = reader->ReadTwoBytes(start);
+ oplen += 2;
+
+ // Check if the lsm passes "pc". If so, mark it as passed.
+ if (lsm_passes_pc &&
+ lsm->address <= pc && pc < lsm->address + advance_address) {
+ *lsm_passes_pc = true;
+ }
+
+ lsm->address += advance_address;
+ }
+ break;
+ case DW_LNS_const_add_pc: {
+ const int64 advance_address = header.min_insn_length
+ * ((255 - header.opcode_base)
+ / header.line_range);
+
+ // Check if the lsm passes "pc". If so, mark it as passed.
+ if (lsm_passes_pc &&
+ lsm->address <= pc && pc < lsm->address + advance_address) {
+ *lsm_passes_pc = true;
+ }
+
+ lsm->address += advance_address;
+ }
+ break;
+ case DW_LNS_extended_op: {
+ const size_t extended_op_len = reader->ReadUnsignedLEB128(start,
+ &templen);
+ start += templen;
+ oplen += templen + extended_op_len;
+
+ const uint64 extended_op = reader->ReadOneByte(start);
+ start++;
+
+ switch (extended_op) {
+ case DW_LNE_end_sequence: {
+ lsm->end_sequence = true;
+ *len = oplen;
+ return true;
+ }
+ break;
+ case DW_LNE_set_address: {
+ // With gcc 4.2.1, we cannot tell the line_no here since
+ // DW_LNE_set_address is called before DW_LNS_advance_line is
+ // called. So we do not check if the lsm passes "pc" here. See
+ // also the comment in DW_LNS_advance_line.
+ uint64 address = reader->ReadAddress(start);
+ lsm->address = address;
+ }
+ break;
+ case DW_LNE_define_file: {
+ const char* filename = start;
+
+ templen = strlen(filename) + 1;
+ start += templen;
+
+ uint64 dirindex = reader->ReadUnsignedLEB128(start, &templen);
+ oplen += templen;
+
+ const uint64 mod_time = reader->ReadUnsignedLEB128(start,
+ &templen);
+ oplen += templen;
+
+ const uint64 filelength = reader->ReadUnsignedLEB128(start,
+ &templen);
+ oplen += templen;
+
+ if (handler) {
+ handler->DefineFile(filename, -1, dirindex, mod_time,
+ filelength);
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ default: {
+ // Ignore unknown opcode silently
+ if (header.std_opcode_lengths) {
+ for (int i = 0; i < (*header.std_opcode_lengths)[opcode]; i++) {
+ size_t templen;
+ reader->ReadUnsignedLEB128(start, &templen);
+ start += templen;
+ oplen += templen;
+ }
+ }
+ }
+ break;
+ }
+ *len = oplen;
+ return false;
+}
+
+void LineInfo::ReadLines() {
+ struct LineStateMachine lsm;
+
+ // lengthstart is the place the length field is based on.
+ // It is the point in the header after the initial length field
+ const char* lengthstart = buffer_;
+
+ // In 64 bit dwarf, the initial length is 12 bytes, because of the
+ // 0xffffffff at the start.
+ if (reader_->OffsetSize() == 8)
+ lengthstart += 12;
+ else
+ lengthstart += 4;
+
+ const char* lineptr = after_header_;
+ while (lineptr < lengthstart + header_.total_length) {
+ lsm.Reset(header_.default_is_stmt);
+ while (!lsm.end_sequence) {
+ size_t oplength;
+ bool add_line = ProcessOneOpcode(reader_, handler_, header_,
+ lineptr, &lsm, &oplength, (uintptr_t)-1, NULL);
+ if (add_line)
+ handler_->AddLine(lsm.address, lsm.file_num, lsm.line_num,
+ lsm.column_num);
+ lineptr += oplength;
+ }
+ }
+
+ after_header_ = lengthstart + header_.total_length;
+}
+
+} // namespace dwarf2reader
Added: trunk/google-breakpad/src/common/mac/dwarf/dwarf2reader.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/dwarf2reader.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,393 @@
+// Copyright 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.
+
+// This file contains definitions related to the DWARF2/3 reader and
+// it's handler interfaces.
+// The DWARF2/3 specification can be found at
+// http://dwarf.freestandards.org and should be considered required
+// reading if you wish to modify the implementation.
+// Only a cursory attempt is made to explain terminology that is
+// used here, as it is much better explained in the standard documents
+#ifndef COMMON_MAC_DWARF_DWARF2READER_H__
+#define COMMON_MAC_DWARF_DWARF2READER_H__
+
+#include <ext/hash_map>
+#include <list>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "common/mac/dwarf/dwarf2enums.h"
+#include "common/mac/dwarf/types.h"
+
+using namespace std;
+using namespace __gnu_cxx;
+
+namespace dwarf2reader {
+struct LineStateMachine;
+class ByteReader;
+class Dwarf2Handler;
+class LineInfoHandler;
+
+// This maps from a string naming a section to a pair containing a
+// the data for the section, and the size of the section.
+typedef hash_map<string, pair<const char*, uint64> > SectionMap;
+typedef list<pair<enum DwarfAttribute, enum DwarfForm> > AttributeList;
+typedef AttributeList::iterator AttributeIterator;
+typedef AttributeList::const_iterator ConstAttributeIterator;
+
+struct LineInfoHeader {
+ uint64 total_length;
+ uint16 version;
+ uint64 prologue_length;
+ uint8 min_insn_length; // insn stands for instructin
+ bool default_is_stmt; // stmt stands for statement
+ int8 line_base;
+ uint8 line_range;
+ uint8 opcode_base;
+ // Use a pointer so that signalsafe_addr2line is able to use this structure
+ // without heap allocation problem.
+ vector<unsigned char> *std_opcode_lengths;
+};
+
+class LineInfo {
+ public:
+
+ // Initializes a .debug_line reader. Buffer and buffer length point
+ // to the beginning and length of the line information to read.
+ // Reader is a ByteReader class that has the endianness set
+ // properly.
+ LineInfo(const char* buffer_, uint64 buffer_length,
+ ByteReader* reader, LineInfoHandler* handler);
+
+ virtual ~LineInfo() {
+ if (header_.std_opcode_lengths) {
+ delete header_.std_opcode_lengths;
+ }
+ }
+
+ // Start processing line info, and calling callbacks in the handler.
+ // Consumes the line number information for a single compilation unit.
+ // Returns the number of bytes processed.
+ uint64 Start();
+
+ // Process a single line info opcode at START using the state
+ // machine at LSM. Return true if we should define a line using the
+ // current state of the line state machine. Place the length of the
+ // opcode in LEN.
+ // If LSM_PASSES_PC is non-NULL, this function also checks if the lsm
+ // passes the address of PC. In other words, LSM_PASSES_PC will be
+ // set to true, if the following condition is met.
+ //
+ // lsm's old address < PC <= lsm's new address
+ static bool ProcessOneOpcode(ByteReader* reader,
+ LineInfoHandler* handler,
+ const struct LineInfoHeader &header,
+ const char* start,
+ struct LineStateMachine* lsm,
+ size_t* len,
+ uintptr_t pc,
+ bool *lsm_passes_pc);
+
+ private:
+ // Reads the DWARF2/3 header for this line info.
+ void ReadHeader();
+
+ // Reads the DWARF2/3 line information
+ void ReadLines();
+
+ // The associated handler to call processing functions in
+ LineInfoHandler* handler_;
+
+ // The associated ByteReader that handles endianness issues for us
+ ByteReader* reader_;
+
+ // A DWARF2/3 line info header. This is not the same size as
+ // in the actual file, as the one in the file may have a 32 bit or
+ // 64 bit lengths
+
+ struct LineInfoHeader header_;
+
+ // buffer is the buffer for our line info, starting at exactly where
+ // the line info to read is. after_header is the place right after
+ // the end of the line information header.
+ const char* buffer_;
+ uint64 buffer_length_;
+ const char* after_header_;
+};
+
+// This class is the main interface between the line info reader and
+// the client. The virtual functions inside this get called for
+// interesting events that happen during line info reading. The
+// default implementation does nothing
+
+class LineInfoHandler {
+ public:
+ LineInfoHandler() { }
+
+ virtual ~LineInfoHandler() { }
+
+ // Called when we define a directory. NAME is the directory name,
+ // DIR_NUM is the directory number
+ virtual void DefineDir(const string& name, uint32 dir_num) { }
+
+ // Called when we define a filename. NAME is the filename, FILE_NUM
+ // is the file number which is -1 if the file index is the next
+ // index after the last numbered index (this happens when files are
+ // dynamically defined by the line program), DIR_NUM is the
+ // directory index for the directory name of this file, MOD_TIME is
+ // the modification time of the file, and LENGTH is the length of
+ // the file
+ virtual void DefineFile(const string& name, int32 file_num,
+ uint32 dir_num, uint64 mod_time,
+ uint64 length) { }
+
+ // Called when the line info reader has a new line, address pair
+ // ready for us. ADDRESS is the address of the code, FILE_NUM is
+ // the file number containing the code, LINE_NUM is the line number in
+ // that file for the code, and COLUMN_NUM is the column number the code
+ // starts at, if we know it (0 otherwise).
+ virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num,
+ uint32 column_num) { }
+};
+
+// The base of DWARF2/3 debug info is a DIE (Debugging Information
+// Entry.
+// DWARF groups DIE's into a tree and calls the root of this tree a
+// "compilation unit". Most of the time, their is one compilation
+// unit in the .debug_info section for each file that had debug info
+// generated.
+// Each DIE consists of
+
+// 1. a tag specifying a thing that is being described (ie
+// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
+// 2. attributes (such as DW_AT_location for location in memory,
+// DW_AT_name for name), and data for each attribute.
+// 3. A flag saying whether the DIE has children or not
+
+// In order to gain some amount of compression, the format of
+// each DIE (tag name, attributes and data forms for the attributes)
+// are stored in a separate table called the "abbreviation table".
+// This is done because a large number of DIEs have the exact same tag
+// and list of attributes, but different data for those attributes.
+// As a result, the .debug_info section is just a stream of data, and
+// requires reading of the .debug_abbrev section to say what the data
+// means.
+
+// As a warning to the user, it should be noted that the reason for
+// using absolute offsets from the beginning of .debug_info is that
+// DWARF2/3 support referencing DIE's from other DIE's by their offset
+// from either the current compilation unit start, *or* the beginning
+// of the .debug_info section. This means it is possible to reference
+// a DIE in one compilation unit from a DIE in another compilation
+// unit. This style of reference is usually used to eliminate
+// duplicated information that occurs across compilation
+// units, such as base types, etc. GCC 3.4+ support this with
+// -feliminate-dwarf2-dups. Other toolchains will sometimes do
+// duplicate elimination in the linker.
+
+class CompilationUnit {
+ public:
+
+ // Initialize a compilation unit. This requires a map of sections,
+ // the offset of this compilation unit in the debug_info section, a
+ // ByteReader, and a Dwarf2Handler class to call callbacks in.
+ CompilationUnit(const SectionMap& sections, uint64 offset,
+ ByteReader* reader, Dwarf2Handler* handler);
+ virtual ~CompilationUnit() {
+ if (abbrevs_) delete abbrevs_;
+ }
+
+ // Begin reading a Dwarf2 compilation unit, and calling the
+ // callbacks in the Dwarf2Handler
+ // Return the offset of the end of the compilation unit - the passed
+ // in offset.
+ uint64 Start();
+
+ private:
+
+ // This struct represents a single DWARF2/3 abbreviation
+ // The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
+ // tag and a list of attributes, as well as the data form of each attribute.
+ struct Abbrev {
+ uint32 number;
+ enum DwarfTag tag;
+ bool has_children;
+ AttributeList attributes;
+ };
+
+ // A DWARF2/3 compilation unit header. This is not the same size as
+ // in the actual file, as the one in the file may have a 32 bit or
+ // 64 bit length.
+ struct CompilationUnitHeader {
+ uint64 length;
+ uint16 version;
+ uint64 abbrev_offset;
+ uint8 address_size;
+ } header_;
+
+ // Reads the DWARF2/3 header for this compilation unit.
+ void ReadHeader();
+
+ // Reads the DWARF2/3 abbreviations for this compilation unit
+ void ReadAbbrevs();
+
+ // Processes a single DIE for this compilation unit and return a new
+ // pointer just past the end of it
+ const char* ProcessDIE(uint64 dieoffset,
+ const char* start,
+ const Abbrev& abbrev);
+
+ // Processes a single attribute and return a new pointer just past the
+ // end of it
+ const char* ProcessAttribute(uint64 dieoffset,
+ const char* start,
+ enum DwarfAttribute attr,
+ enum DwarfForm form);
+
+ // Processes all DIEs for this compilation unit
+ void ProcessDIEs();
+
+ // Skips the die with attributes specified in ABBREV starting at
+ // START, and return the new place to position the stream to.
+ const char* SkipDIE(const char* start,
+ const Abbrev& abbrev);
+
+ // Skips the attribute starting at START, with FORM, and return the
+ // new place to position the stream to.
+ const char* SkipAttribute(const char* start,
+ enum DwarfForm form);
+
+ // Offset from section start is the offset of this compilation unit
+ // from the beginning of the .debug_info section.
+ uint64 offset_from_section_start_;
+
+ // buffer is the buffer for our CU, starting at .debug_info + offset
+ // passed in from constructor.
+ // after_header points to right after the compilation unit header.
+ const char* buffer_;
+ uint64 buffer_length_;
+ const char* after_header_;
+
+ // The associated ByteReader that handles endianness issues for us
+ ByteReader* reader_;
+
+ // The map of sections in our file to buffers containing their data
+ const SectionMap& sections_;
+
+ // The associated handler to call processing functions in
+ Dwarf2Handler* handler_;
+
+ // Set of DWARF2/3 abbreviations for this compilation unit. Indexed
+ // by abbreviation number, which means that abbrevs_[0] is not
+ // valid.
+ vector<Abbrev>* abbrevs_;
+
+ // String section buffer and length, if we have a string section.
+ // This is here to avoid doing a section lookup for strings in
+ // ProcessAttribute, which is in the hot path for DWARF2 reading.
+ const char* string_buffer_;
+ uint64 string_buffer_length_;
+};
+
+// This class is the main interface between the reader and the
+// client. The virtual functions inside this get called for
+// interesting events that happen during DWARF2 reading.
+// The default implementation skips everything.
+
+class Dwarf2Handler {
+ public:
+ Dwarf2Handler() { }
+
+ virtual ~Dwarf2Handler() { }
+
+ // Start to process a compilation unit at OFFSET from the beginning of the
+ // debug_info section. Return false if you would like
+ // to skip this compilation unit.
+ virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
+ uint8 offset_size, uint64 cu_length,
+ uint8 dwarf_version) { return false; }
+
+ // Start to process a DIE at OFFSET from the beginning of the
+ // debug_info section. Return false if you would like to skip this
+ // DIE.
+ virtual bool StartDIE(uint64 offset, enum DwarfTag tag,
+ const AttributeList& attrs) { return false; }
+
+ // Called when we have an attribute with unsigned data to give to
+ // our handler. The attribute is for the DIE at OFFSET from the
+ // beginning of compilation unit, has a name of ATTR, a form of
+ // FORM, and the actual data of the attribute is in DATA.
+ virtual void ProcessAttributeUnsigned(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64 data) { }
+
+ // Called when we have an attribute with signed data to give to
+ // our handler. The attribute is for the DIE at OFFSET from the
+ // beginning of compilation unit, has a name of ATTR, a form of
+ // FORM, and the actual data of the attribute is in DATA.
+ virtual void ProcessAttributeSigned(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ int64 data) { }
+
+ // Called when we have an attribute with a buffer of data to give to
+ // our handler. The attribute is for the DIE at OFFSET from the
+ // beginning of compilation unit, has a name of ATTR, a form of
+ // FORM, and the actual data of the attribute is in DATA, and the
+ // length of the buffer is LENGTH. The buffer is owned by the
+ // caller, not the callee, and may not persist for very long. If
+ // you want the data to be available later, it needs to be copied.
+ virtual void ProcessAttributeBuffer(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ const char* data,
+ uint64 len) { }
+
+ // Called when we have an attribute with string data to give to
+ // our handler. The attribute is for the DIE at OFFSET from the
+ // beginning of compilation unit, has a name of ATTR, a form of
+ // FORM, and the actual data of the attribute is in DATA.
+ virtual void ProcessAttributeString(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ const string& data) { }
+
+ // Called when finished processing the DIE at OFFSET.
+ // Because DWARF2/3 specifies a tree of DIEs, you may get starts
+ // before ends of the previous DIE, as we process children before
+ // ending the parent.
+ virtual void EndDIE(uint64 offset) { }
+
+};
+
+
+} // namespace dwarf2reader
+
+#endif // UTIL_DEBUGINFO_DWARF2READER_H__
Added: trunk/google-breakpad/src/common/mac/dwarf/functioninfo.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/functioninfo.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,198 @@
+// Copyright 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.
+
+// This is a client for the dwarf2reader to extract function and line
+// information from the debug info.
+
+#include <map>
+#include <queue>
+#include <vector>
+
+
+#include "common/mac/dwarf/functioninfo.h"
+
+#include "common/mac/dwarf/bytereader.h"
+
+
+namespace __gnu_cxx
+{
+ template<>
+ struct hash<std::string>
+ {
+ size_t operator()(const std::string& k) const;
+ };
+}
+
+
+namespace dwarf2reader {
+
+CULineInfoHandler::CULineInfoHandler(vector<SourceFileInfo>* files,
+ vector<string>* dirs,
+ LineMap* linemap):linemap_(linemap),
+ files_(files),
+ dirs_(dirs) {
+ // The dirs and files are 1 indexed, so just make sure we put
+ // nothing in the 0 vector.
+ assert(dirs->size() == 0);
+ assert(files->size() == 0);
+ dirs->push_back("");
+ SourceFileInfo s;
+ s.name = "";
+ s.lowpc = ULLONG_MAX;
+ files->push_back(s);
+}
+
+void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) {
+ // These should never come out of order, actually
+ assert(dir_num == dirs_->size());
+ dirs_->push_back(name);
+}
+
+void CULineInfoHandler::DefineFile(const string& name,
+ int32 file_num, uint32 dir_num,
+ uint64 mod_time, uint64 length) {
+ assert(dir_num >= 0);
+ assert(dir_num < dirs_->size());
+
+ // These should never come out of order, actually.
+ if (file_num == (int32)files_->size() || file_num == -1) {
+ string dir = dirs_->at(dir_num);
+
+ SourceFileInfo s;
+ s.lowpc = ULLONG_MAX;
+
+ if (dir == "") {
+ s.name = name;
+ } else {
+ s.name = dir + "/" + name;
+ }
+
+ files_->push_back(s);
+ } else {
+ fprintf(stderr, "error in DefineFile");
+ }
+}
+
+void CULineInfoHandler::AddLine(uint64 address, uint32 file_num,
+ uint32 line_num, uint32 column_num) {
+ if (file_num < files_->size()) {
+ linemap_->insert(make_pair(address, make_pair(files_->at(file_num).name.c_str(),
+ line_num)));
+
+ if(address < files_->at(file_num).lowpc) {
+ files_->at(file_num).lowpc = address;
+ }
+ } else {
+ fprintf(stderr,"error in AddLine");
+ }
+}
+
+bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
+ uint8 address_size,
+ uint8 offset_size,
+ uint64 cu_length,
+ uint8 dwarf_version) {
+ return true;
+}
+
+
+// For function info, we only care about subprograms and inlined
+// subroutines. For line info, the DW_AT_stmt_list lives in the
+// compile unit tag.
+
+bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag,
+ const AttributeList& attrs) {
+ switch (tag) {
+ case DW_TAG_subprogram:
+ case DW_TAG_inlined_subroutine: {
+ current_function_info_ = new FunctionInfo;
+ current_function_info_->lowpc = current_function_info_->highpc = 0;
+ current_function_info_->name = "";
+ current_function_info_->line = 0;
+ current_function_info_->file = "";
+ offset_to_funcinfo_->insert(make_pair(offset, current_function_info_));
+ };
+ // FALLTHROUGH
+ case DW_TAG_compile_unit:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+// Only care about the name attribute for functions
+
+void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ const string &data) {
+ if (attr == DW_AT_name && current_function_info_)
+ current_function_info_->name = data;
+}
+
+void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64 data) {
+ if (attr == DW_AT_stmt_list) {
+ SectionMap::const_iterator iter = sections_.find("__debug_line");
+ assert(iter != sections_.end());
+
+ // this should be a scoped_ptr but we dont' use boost :-(
+ auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
+ iter->second.second - data,
+ reader_, linehandler_));
+ lireader->Start();
+ } else if (current_function_info_) {
+ switch (attr) {
+ case DW_AT_low_pc:
+ current_function_info_->lowpc = data;
+ break;
+ case DW_AT_high_pc:
+ current_function_info_->highpc = data;
+ break;
+ case DW_AT_decl_line:
+ current_function_info_->line = data;
+ break;
+ case DW_AT_decl_file:
+ current_function_info_->file = files_->at(data).name;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void CUFunctionInfoHandler::EndDIE(uint64 offset) {
+ if (current_function_info_ && current_function_info_->lowpc)
+ address_to_funcinfo_->insert(make_pair(current_function_info_->lowpc,
+ current_function_info_));
+}
+
+} // namespace dwarf2reader
Added: trunk/google-breakpad/src/common/mac/dwarf/functioninfo.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/functioninfo.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,175 @@
+// Copyright 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.
+
+
+// This file contains the definitions for a DWARF2/3 information
+// collector that uses the DWARF2/3 reader interface to build a mapping
+// of addresses to files, lines, and functions.
+
+#ifndef COMMON_MAC_DWARF_FUNCTIONINFO_H__
+#define COMMON_MAC_DWARF_FUNCTIONINFO_H__
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "common/mac/dwarf/dwarf2reader.h"
+
+
+namespace dwarf2reader {
+
+struct FunctionInfo {
+ // Name of the function
+ string name;
+ // File containing this function
+ string file;
+ // Line number for start of function.
+ uint32 line;
+ // Beginning address for this function
+ uint64 lowpc;
+ // End address for this function.
+ uint64 highpc;
+};
+
+struct SourceFileInfo {
+ // Name of the source file name
+ string name;
+ // Low address of source file name
+ uint64 lowpc;
+};
+
+typedef map<uint64, FunctionInfo*> FunctionMap;
+typedef map<uint64, pair<string, uint32> > LineMap;
+
+// This class is a basic line info handler that fills in the dirs,
+// file, and linemap passed into it with the data produced from the
+// LineInfoHandler.
+class CULineInfoHandler: public LineInfoHandler {
+ public:
+
+ //
+ CULineInfoHandler(vector<SourceFileInfo>* files,
+ vector<string>* dirs,
+ LineMap* linemap);
+ virtual ~CULineInfoHandler() { }
+
+ // Called when we define a directory. We just place NAME into dirs_
+ // at position DIR_NUM.
+ virtual void DefineDir(const string& name, uint32 dir_num);
+
+ // Called when we define a filename. We just place
+ // concat(dirs_[DIR_NUM], NAME) into files_ at position FILE_NUM.
+ virtual void DefineFile(const string& name, int32 file_num,
+ uint32 dir_num, uint64 mod_time, uint64 length);
+
+
+ // Called when the line info reader has a new line, address pair
+ // ready for us. ADDRESS is the address of the code, FILE_NUM is
+ // the file number containing the code, LINE_NUM is the line number
+ // in that file for the code, and COLUMN_NUM is the column number
+ // the code starts at, if we know it (0 otherwise).
+ virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num,
+ uint32 column_num);
+
+
+ private:
+ LineMap* linemap_;
+ vector<SourceFileInfo>* files_;
+ vector<string>* dirs_;
+};
+
+class CUFunctionInfoHandler: public Dwarf2Handler {
+ public:
+ CUFunctionInfoHandler(vector<SourceFileInfo>* files,
+ vector<string>* dirs,
+ LineMap* linemap,
+ FunctionMap* offset_to_funcinfo,
+ FunctionMap* address_to_funcinfo,
+ CULineInfoHandler* linehandler,
+ const SectionMap& sections,
+ ByteReader* reader)
+ : files_(files), dirs_(dirs), linemap_(linemap),
+ offset_to_funcinfo_(offset_to_funcinfo),
+ address_to_funcinfo_(address_to_funcinfo),
+ linehandler_(linehandler), sections_(sections),
+ reader_(reader), current_function_info_(NULL) { }
+
+ virtual ~CUFunctionInfoHandler() { }
+
+ // Start to process a compilation unit at OFFSET from the beginning of the
+ // debug_info section. We want to see all compilation units, so we
+ // always return true.
+
+ virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
+ uint8 offset_size, uint64 cu_length,
+ uint8 dwarf_version);
+
+ // Start to process a DIE at OFFSET from the beginning of the
+ // debug_info section. We only care about function related DIE's.
+ virtual bool StartDIE(uint64 offset, enum DwarfTag tag,
+ const AttributeList& attrs);
+
+ // Called when we have an attribute with unsigned data to give to
+ // our handler. The attribute is for the DIE at OFFSET from the
+ // beginning of compilation unit, has a name of ATTR, a form of
+ // FORM, and the actual data of the attribute is in DATA.
+ virtual void ProcessAttributeUnsigned(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64 data);
+
+ // Called when we have an attribute with string data to give to
+ // our handler. The attribute is for the DIE at OFFSET from the
+ // beginning of compilation unit, has a name of ATTR, a form of
+ // FORM, and the actual data of the attribute is in DATA.
+ virtual void ProcessAttributeString(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ const string& data);
+
+ // Called when finished processing the DIE at OFFSET.
+ // Because DWARF2/3 specifies a tree of DIEs, you may get starts
+ // before ends of the previous DIE, as we process children before
+ // ending the parent.
+ virtual void EndDIE(uint64 offset);
+
+ private:
+ vector<SourceFileInfo>* files_;
+ vector<string>* dirs_;
+ LineMap* linemap_;
+ FunctionMap* offset_to_funcinfo_;
+ FunctionMap* address_to_funcinfo_;
+ CULineInfoHandler* linehandler_;
+ const SectionMap& sections_;
+ ByteReader* reader_;
+ FunctionInfo* current_function_info_;
+};
+
+} // namespace dwarf2reader
+#endif // COMMON_MAC_DWARF_FUNCTIONINFO_H__
Added: trunk/google-breakpad/src/common/mac/dwarf/line_state_machine.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/line_state_machine.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,61 @@
+// Copyright 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 COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__
+#define COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__
+
+namespace dwarf2reader {
+
+// This is the format of a DWARF2/3 line state machine that we process
+// opcodes using. There is no need for anything outside the lineinfo
+// processor to know how this works.
+struct LineStateMachine {
+ void Reset(bool default_is_stmt) {
+ file_num = 1;
+ address = 0;
+ line_num = 1;
+ column_num = 0;
+ is_stmt = default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+ }
+
+ uint32 file_num;
+ uint64 address;
+ uint64 line_num;
+ uint32 column_num;
+ bool is_stmt; // stmt means statement.
+ bool basic_block;
+ bool end_sequence;
+};
+
+} // namespace dwarf2reader
+
+
+#endif // COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__
Added: trunk/google-breakpad/src/common/mac/dwarf/types.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/mac/dwarf/types.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+
+// This file contains some typedefs for basic types
+
+
+#ifndef _COMMON_MAC_DWARF_TYPES_H__
+#define _COMMON_MAC_DWARF_TYPES_H__
+
+typedef signed char int8;
+typedef short int16;
+typedef int int32;
+typedef long long int64;
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+
+#endif // _COMMON_MAC_DWARF_TYPES_H__
Added: trunk/google-breakpad/src/common/md5.c
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/md5.c Sun Oct 19 13:26:38 2008
@@ -0,0 +1,246 @@
+/*
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include <string.h>
+
+#include "common/md5.h"
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len) /* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+ u32 t;
+ do {
+ t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(u32 *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+#endif
+
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ u32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (u32 *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (u32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((u32 *) ctx->in)[14] = ctx->bits[0];
+ ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (u32 *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(u32 buf[4], u32 const in[16])
+{
+ register u32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
Added: trunk/google-breakpad/src/common/md5.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/md5.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,31 @@
+// Copyright 2007 Google Inc. All Rights Reserved.
+// Author: liuli google com (Liu Li)
+#ifndef COMMON_MD5_H__
+#define COMMON_MD5_H__
+
+#include <stdint.h>
+
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+struct MD5Context {
+ u32 buf[4];
+ u32 bits[2];
+ u8 in[64];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+void MD5Init(struct MD5Context *ctx);
+
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len);
+
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COMMON_MD5_H__
Added: trunk/google-breakpad/src/common/solaris/dump_symbols.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/solaris/dump_symbols.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,680 @@
+// Copyright (c) 2007, 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.
+
+// Author: Alfred Peng
+
+#include <demangle.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <link.h>
+#include <sys/mman.h>
+#include <stab.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <functional>
+#include <map>
+#include <vector>
+
+#include "common/solaris/dump_symbols.h"
+#include "common/solaris/file_id.h"
+#include "common/solaris/guid_creator.h"
+#include "processor/scoped_ptr.h"
+
+// This namespace contains helper functions.
+namespace {
+
+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;
+ // Stab type.
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ 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.
+ // Load from stab symbol.
+ GElf_Off rva_to_func;
+ // Offset from base of the loading binary.
+ GElf_Off rva_to_base;
+ // Size of the line.
+ // The first line: equals to rva_to_func.
+ // The other lines: the difference of rva_to_func of the line and
+ // rva_to_func of the previous N_SLINE.
+ uint32_t size;
+ // Line number.
+ uint32_t line_num;
+};
+
+// Information of a function.
+struct FuncInfo {
+ // Name of the function.
+ const char *name;
+ // Offset from the base of the loading address.
+ GElf_Off rva_to_base;
+ // Virtual address of the function.
+ // Load from stab symbol.
+ GElf_Addr addr;
+ // Size of the function.
+ // Equal to rva_to_func of the last function line.
+ uint32_t size;
+ // Total size of stack parameters.
+ uint32_t stack_param_size;
+ // Line information array.
+ std::vector<struct LineInfo> line_info;
+};
+
+// Information of a source file.
+struct SourceFileInfo {
+ // Name of the source file.
+ const char *name;
+ // Starting address of the source file.
+ GElf_Addr addr;
+ // Id of the source file.
+ int source_id;
+ // Functions information.
+ 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.
+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 = 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) {
+ int status = 0;
+ char *demangled = (char *)malloc(demangleLen);
+ if (!demangled) {
+ fprintf(stderr, "no enough memory.\n");
+ goto out;
+ }
+
+ if ((status = cplus_demangle(mangled, demangled, demangleLen)) ==
+ DEMANGLE_ESPACE) {
+ fprintf(stderr, "incorrect demangle.\n");
+ goto out;
+ }
+
+ std::string str(demangled);
+ free(demangled);
+ return str;
+
+out:
+ return std::string(mangled);
+}
+
+bool WriteFormat(int fd, const char *fmt, ...) {
+ va_list list;
+ char buffer[4096];
+ ssize_t expected, written;
+ va_start(list, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, list);
+ expected = strlen(buffer);
+ written = write(fd, buffer, strlen(buffer));
+ va_end(list);
+ return expected == written;
+}
+
+bool IsValidElf(const GElf_Ehdr *elf_header) {
+ return memcmp(elf_header, ELFMAG, SELFMAG) == 0;
+}
+
+static bool FindSectionByName(Elf *elf, const char *name,
+ int shstrndx,
+ GElf_Shdr *shdr) {
+ assert(name != NULL);
+
+ if (strlen(name) == 0)
+ return false;
+
+ Elf_Scn *scn = NULL;
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if (gelf_getshdr(scn, shdr) == (GElf_Shdr *)0) {
+ fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0));
+ return false;
+ }
+
+ const char *section_name = elf_strptr(elf, shstrndx, shdr->sh_name);
+ if (!section_name) {
+ fprintf(stderr, "Section name error: %s\n", elf_errmsg(-1));
+ continue;
+ }
+
+ if (strcmp(section_name, name) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+// The parameter size is used for FPO-optimized code, and
+// this is all tied up with the debugging data for Windows x86.
+// Set it to 0 on Solaris.
+int LoadStackParamSize(struct slist *list,
+ struct slist *list_end,
+ struct FuncInfo *func_info) {
+ struct slist *cur_list = list;
+ int step = 1;
+ while (cur_list < list_end && cur_list->n_type == N_PSYM) {
+ ++cur_list;
+ ++step;
+ }
+
+ func_info->stack_param_size = 0;
+ return step;
+}
+
+int LoadLineInfo(struct slist *list,
+ struct slist *list_end,
+ struct FuncInfo *func_info) {
+ struct slist *cur_list = 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, 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;
+ while (cur_list < list_end && cur_list->n_type == N_SLINE) {
+ line.rva_to_func = cur_list->n_value;
+ // n_desc is a signed short
+ line.line_num = (unsigned short)cur_list->n_desc;
+ func_info->line_info.push_back(line);
+ ++cur_list;
+ }
+ if (cur_list == list_end && cur_list->n_type == N_ENDM)
+ break;
+ } while (list < list_end);
+
+ return cur_list - list;
+}
+
+int LoadFuncSymbols(struct slist *list,
+ struct slist *list_end,
+ char *stabstr,
+ GElf_Word base,
+ struct SourceFileInfo *source_file_info) {
+ struct slist *cur_list = list;
+ assert(cur_list->n_type == N_SO);
+ ++cur_list;
+
+ source_file_info->func_info.clear();
+ while (cur_list < list_end) {
+ // Go until the function symbol.
+ while (cur_list < list_end && cur_list->n_type != N_FUN) {
+ if (cur_list->n_type == N_SO) {
+ 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 = 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.
+ cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
+ // 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.
+ //
+ // These two values are always 0 with Sun CC.
+ // TODO(Alfred): Get the correct value or remove the condition statement.
+ if (func_info.addr >= source_file_info->addr) {
+ source_file_info->func_info.push_back(func_info);
+ }
+ }
+ }
+ return cur_list - list;
+}
+
+// Compute size and rva information based on symbols loaded from stab section.
+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);
+ int func_size = sorted_functions->size();
+
+ for (size_t j = 0; j < func_size; ++j) {
+ struct FuncInfo &func_info = (*sorted_functions)[j];
+ int line_count = func_info.line_info.size();
+
+ // 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];
+
+ 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_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;
+ struct slist *cur_list = lists + i;
+ if (cur_list->n_type == N_SO) {
+ // FUNC <address> <size> <param_stack_size> <function>
+ struct SourceFileInfo source_file_info;
+ 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;
+ if (strchr(source_file_info.name, '.'))
+ source_file_info.source_id = source_id++;
+ else
+ source_file_info.source_id = -1;
+ 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(symbols);
+}
+
+bool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols,
+ void *obj_base) {
+ GElf_Word base = reinterpret_cast<GElf_Word>(obj_base);
+
+ const GElf_Shdr *sections =
+ reinterpret_cast<GElf_Shdr *>(elf_header->e_shoff + base);
+ GElf_Shdr stab_section;
+ if (!FindSectionByName(elf, kStabName, elf_header->e_shstrndx,
+ &stab_section)) {
+ fprintf(stderr, "Stab section not found.\n");
+ return false;
+ }
+ GElf_Shdr stabstr_section;
+ if (!FindSectionByName(elf, kStabStrName, elf_header->e_shstrndx,
+ &stabstr_section)) {
+ 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, base, symbols);
+}
+
+bool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) {
+ const char *arch_name = NULL;
+ if (arch == EM_386)
+ arch_name = "x86";
+ else if (arch == EM_X86_64)
+ arch_name = "x86_64";
+ 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());
+ if (file_id.ElfFileIdentifier(identifier)) {
+ char identifier_str[40];
+ file_id.ConvertIdentifierToString(identifier,
+ identifier_str, sizeof(identifier_str));
+ std::string filename = obj_file;
+ size_t slash_pos = obj_file.find_last_of("/");
+ if (slash_pos != std::string::npos)
+ filename = obj_file.substr(slash_pos + 1);
+ return WriteFormat(fd, "MODULE solaris %s %s %s\n", arch_name,
+ identifier_str, filename.c_str());
+ }
+ return false;
+}
+
+bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) {
+ for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
+ if (symbols.source_file_info[i].source_id != -1) {
+ const char *name = symbols.source_file_info[i].name;
+ if (!WriteFormat(fd, "FILE %d %s\n",
+ symbols.source_file_info[i].source_id, name))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WriteOneFunction(int fd, int source_id,
+ const struct FuncInfo &func_info){
+ // Discard the ending part of the name.
+ std::string func_name(func_info.name);
+ std::string::size_type last_colon = func_name.find_last_of(':');
+ if (last_colon != std::string::npos)
+ func_name = func_name.substr(0, last_colon);
+ func_name = Demangle(func_name.c_str());
+
+ 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 %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 (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,
+ source_id))
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
+ for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
+ const struct SourceFileInfo &file_info = symbols.source_file_info[i];
+ for (size_t j = 0; j < file_info.func_info.size(); ++j) {
+ const struct FuncInfo &func_info = file_info.func_info[j];
+ if (!WriteOneFunction(fd, file_info.source_id, func_info))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) {
+ return WriteSourceFileInfo(fd, symbols) &&
+ WriteFunctionInfo(fd, symbols);
+}
+
+//
+// FDWrapper
+//
+// Wrapper class to make sure opened file is closed.
+//
+class FDWrapper {
+ public:
+ explicit FDWrapper(int fd) :
+ fd_(fd) {
+ }
+ ~FDWrapper() {
+ if (fd_ != -1)
+ close(fd_);
+ }
+ int get() {
+ return fd_;
+ }
+ int release() {
+ int fd = fd_;
+ fd_ = -1;
+ return fd;
+ }
+ private:
+ int fd_;
+};
+
+//
+// MmapWrapper
+//
+// Wrapper class to make sure mapped regions are unmapped.
+//
+class MmapWrapper {
+ public:
+ MmapWrapper(void *mapped_address, size_t mapped_size) :
+ base_(mapped_address), size_(mapped_size) {
+ }
+ ~MmapWrapper() {
+ if (base_ != NULL) {
+ assert(size_ > 0);
+ munmap((char *)base_, size_);
+ }
+ }
+ void release() {
+ base_ = NULL;
+ size_ = 0;
+ }
+
+ private:
+ void *base_;
+ size_t size_;
+};
+
+} // namespace
+
+namespace google_breakpad {
+
+class AutoElfEnder {
+ public:
+ AutoElfEnder(Elf *elf) : elf_(elf) {}
+ ~AutoElfEnder() { if (elf_) elf_end(elf_); }
+ private:
+ Elf *elf_;
+};
+
+
+bool DumpSymbols::WriteSymbolFile(const std::string &obj_file, int sym_fd) {
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0));
+ return false;
+ }
+
+ int obj_fd = open(obj_file.c_str(), O_RDONLY);
+ if (obj_fd < 0)
+ return false;
+ FDWrapper obj_fd_wrapper(obj_fd);
+ struct stat st;
+ if (fstat(obj_fd, &st) != 0 && st.st_size <= 0)
+ return false;
+ void *obj_base = mmap(NULL, st.st_size,
+ PROT_READ, MAP_PRIVATE, obj_fd, 0);
+ if (!obj_base)
+ return false;
+ MmapWrapper map_wrapper(obj_base, st.st_size);
+ GElf_Ehdr elf_header;
+ Elf *elf = elf_begin(obj_fd, ELF_C_READ, NULL);
+ AutoElfEnder elfEnder(elf);
+
+ if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) {
+ fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1));
+ return false;
+ }
+
+ if (!IsValidElf(&elf_header)) {
+ fprintf(stderr, "header magic doesn't match\n");
+ return false;
+ }
+ struct SymbolInfo symbols;
+ if (!LoadSymbols(elf, &elf_header, &symbols, obj_base))
+ return false;
+ // Write to symbol file.
+ if (WriteModuleInfo(sym_fd, elf_header.e_machine, obj_file) &&
+ DumpStabSymbols(sym_fd, symbols))
+ return true;
+
+ return false;
+}
+
+} // namespace google_breakpad
Added: trunk/google-breakpad/src/common/solaris/dump_symbols.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/common/solaris/dump_symbols.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,49 @@
+// Copyright (c) 2007, 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.
+//
+// dump_symbols.cc: Implements a Solaris stab debugging format dumper.
+//
+// Author: Alfred Peng
+
+#ifndef COMMON_SOLARIS_DUMP_SYMBOLS_H__
+#define COMMON_SOLARIS_DUMP_SYMBOLS_H__
+
+#include <string>
+
+namespace google_breakpad {
+
+class DumpSymbols {
+ public:
+ bool WriteSymbolFile(const std::string &obj_file,
+ int sym_fd);
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_SOLARIS_DUMP_SYMBOLS_H__
Modified: trunk/google-breakpad/src/common/solaris/file_id.cc
==============================================================================
--- trunk/google-breakpad/src/common/solaris/file_id.cc (original)
+++ trunk/google-breakpad/src/common/solaris/file_id.cc Sun Oct 19 13:26:38 2008
@@ -36,8 +36,6 @@
#include <elf.h>
#include <fcntl.h>
#include <gelf.h>
-#include <gnutls/openssl.h>
-#include <link.h>
#include <sys/mman.h>
#include <sys/ksyms.h>
#include <stdio.h>
@@ -47,6 +45,7 @@
#include <cassert>
#include <cstdio>
+#include "common/md5.h"
#include "common/solaris/file_id.h"
#include "common/solaris/message_output.h"
#include "google_breakpad/common/minidump_format.h"
@@ -130,7 +129,7 @@
}
FileID::FileID(const char *path) {
- strncpy(path_, path, strlen(path));
+ strcpy(path_, path);
}
class AutoCloser {
@@ -160,10 +159,10 @@
int text_size = 0;
if (FindElfTextSection(fd, base, &text_section, &text_size)) {
- MD5_CTX md5;
- MD5_Init(&md5);
- MD5_Update(&md5, text_section, text_size);
- MD5_Final(identifier, &md5);
+ MD5Context md5;
+ MD5Init(&md5);
+ MD5Update(&md5, (const unsigned char *)text_section, text_size);
+ MD5Final(identifier, &md5);
success = true;
}
Modified: trunk/google-breakpad/src/common/string_conversion.cc
==============================================================================
--- trunk/google-breakpad/src/common/string_conversion.cc (original)
+++ trunk/google-breakpad/src/common/string_conversion.cc Sun Oct 19 13:26:38 2008
@@ -34,6 +34,7 @@
#include "common/convert_UTF.h"
#include "processor/scoped_ptr.h"
#include "common/string_conversion.h"
+#include <string.h>
namespace google_breakpad {
Modified: trunk/google-breakpad/src/common/windows/http_upload.cc
==============================================================================
--- trunk/google-breakpad/src/common/windows/http_upload.cc (original)
+++ trunk/google-breakpad/src/common/windows/http_upload.cc Sun Oct 19 13:26:38 2008
@@ -83,11 +83,11 @@
memset(&components, 0, sizeof(components));
components.dwStructSize = sizeof(components);
components.lpszScheme = scheme;
- components.dwSchemeLength = sizeof(scheme);
+ components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]);
components.lpszHostName = host;
- components.dwHostNameLength = sizeof(host);
+ components.dwHostNameLength = sizeof(host) / sizeof(host[0]);
components.lpszUrlPath = path;
- components.dwUrlPathLength = sizeof(path);
+ components.dwUrlPathLength = sizeof(path) / sizeof(path[0]);
if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
0, &components)) {
return false;
@@ -137,7 +137,8 @@
wstring content_type_header = GenerateRequestHeader(boundary);
HttpAddRequestHeaders(request.get(),
content_type_header.c_str(),
- -1, HTTP_ADDREQ_FLAG_ADD);
+ static_cast<DWORD>(-1),
+ HTTP_ADDREQ_FLAG_ADD);
string request_body;
if (!GenerateRequestBody(parameters, upload_file,
Modified: trunk/google-breakpad/src/common/windows/string_utils-inl.h
==============================================================================
--- trunk/google-breakpad/src/common/windows/string_utils-inl.h (original)
+++ trunk/google-breakpad/src/common/windows/string_utils-inl.h Sun Oct 19 13:26:38 2008
@@ -56,6 +56,10 @@
// _snwprintf when using older CRTs.
#if _MSC_VER < 1400 // MSVC 2005/8
#define swprintf _snwprintf
+#else
+// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently,
+// it takes the same argument list as swprintf.
+#define swprintf swprintf_s
#endif // MSC_VER < 1400
namespace google_breakpad {
Modified: trunk/google-breakpad/src/google_breakpad/common/breakpad_types.h
==============================================================================
--- trunk/google-breakpad/src/google_breakpad/common/breakpad_types.h (original)
+++ trunk/google-breakpad/src/google_breakpad/common/breakpad_types.h Sun Oct 19 13:26:38 2008
@@ -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 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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,155 @@
+/* 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
+
+/* Use the same 32-bit alignment when accessing this structure from 64-bit code
+ * as is used natively in 32-bit code. #pragma pack is a MSVC extension
+ * supported by gcc. */
+#pragma pack(push, 4)
+
+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 */
+
+#pragma pack(pop)
+
+/* 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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Added: trunk/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h Sun Oct 19 13:26:38 2008
@@ -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__ */
Modified: trunk/google-breakpad/src/google_breakpad/common/minidump_format.h
==============================================================================
--- trunk/google-breakpad/src/google_breakpad/common/minidump_format.h (original)
+++ trunk/google-breakpad/src/google_breakpad/common/minidump_format.h Sun Oct 19 13:26:38 2008
@@ -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 @@
* 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,93 +104,6 @@
#define MD_CONTEXT_CPU_MASK 0xffffffc0
-/*
- * 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
@@ -310,73 +112,11 @@
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"
/*
@@ -492,7 +232,6 @@
* MDRawHeader is at offset 0. */
typedef u_int32_t MDRVA; /* RVA */
-
typedef struct {
u_int32_t data_size;
MDRVA rva;
@@ -771,292 +510,10 @@
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
Modified: trunk/google-breakpad/src/google_breakpad/processor/minidump.h
==============================================================================
--- trunk/google-breakpad/src/google_breakpad/processor/minidump.h (original)
+++ trunk/google-breakpad/src/google_breakpad/processor/minidump.h Sun Oct 19 13:26:38 2008
@@ -79,6 +79,7 @@
#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
+#include <unistd.h>
#include <map>
#include <string>
@@ -108,6 +109,8 @@
public:
virtual ~MinidumpObject() {}
+ bool valid() const { return valid_; }
+
protected:
explicit MinidumpObject(Minidump* minidump);
@@ -175,8 +178,9 @@
// Returns raw CPU-specific context data for the named CPU type. If the
// context data does not match the CPU type or does not exist, returns
// NULL.
- const MDRawContextX86* GetContextX86() const;
- const MDRawContextPPC* GetContextPPC() const;
+ const MDRawContextX86* GetContextX86() const;
+ const MDRawContextPPC* GetContextPPC() const;
+ const MDRawContextAMD64* GetContextAMD64() const;
const MDRawContextSPARC* GetContextSPARC() const;
// Print a human-readable representation of the object to stdout.
@@ -200,11 +204,15 @@
// not contain a system info stream.
bool CheckAgainstSystemInfo(u_int32_t context_cpu_type);
+ // Store this separately because of the weirdo AMD64 context
+ u_int32_t context_flags_;
+
// The CPU-specific context structure.
union {
- MDRawContextBase* base;
- MDRawContextX86* x86;
- MDRawContextPPC* ppc;
+ MDRawContextBase* base;
+ MDRawContextX86* x86;
+ MDRawContextPPC* ppc;
+ MDRawContextAMD64* amd64;
// on Solaris SPARC, sparc is defined as a numeric constant,
// so variables can NOT be named as sparc
MDRawContextSPARC* ctx_sparc;
@@ -451,6 +459,11 @@
// be read.
bool module_valid_;
+ // True if debug info was read from the module. Certain modules
+ // may contain debug records in formats we don't support,
+ // so we can just set this to false to ignore them.
+ bool has_debug_info_;
+
MDRawModule module_;
// Cached module name.
@@ -794,6 +807,9 @@
// Sets the position of the minidump file to offset.
bool SeekSet(off_t offset);
+ // Returns the current position of the minidump file.
+ off_t Tell() { return valid_ ? lseek(fd_, 0, SEEK_CUR) : (off_t)-1; }
+
// The next 2 methods are medium-level I/O routines.
// ReadString returns a string which is owned by the caller! offset
Modified: trunk/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h
==============================================================================
--- trunk/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h (original)
+++ trunk/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h Sun Oct 19 13:26:38 2008
@@ -98,13 +98,39 @@
int context_validity;
};
+struct StackFrameAMD64 : public StackFrame {
+ // ContextValidity has one entry for each relevant hardware pointer register
+ // (%rip and %rsp) and one entry for each nonvolatile (callee-save) register.
+ //FIXME: validate this list
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_RIP = 1 << 0,
+ CONTEXT_VALID_RSP = 1 << 1,
+ CONTEXT_VALID_RBP = 1 << 2,
+ CONTEXT_VALID_ALL = -1
+ };
+
+ StackFrameAMD64() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextAMD64 context;
+
+ // context_validity is actually ContextValidity, but int is used because
+ // the OR operator doesn't work well with enumerated types. This indicates
+ // which fields in context are valid.
+ int context_validity;
+};
+
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
};
Modified: trunk/google-breakpad/src/processor/logging.cc
==============================================================================
--- trunk/google-breakpad/src/processor/logging.cc (original)
+++ trunk/google-breakpad/src/processor/logging.cc Sun Oct 19 13:26:38 2008
@@ -80,7 +80,7 @@
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);
}
Modified: trunk/google-breakpad/src/processor/minidump.cc
==============================================================================
--- trunk/google-breakpad/src/processor/minidump.cc (original)
+++ trunk/google-breakpad/src/processor/minidump.cc Sun Oct 19 13:26:38 2008
@@ -36,7 +36,6 @@
#include <fcntl.h>
#include <stdio.h>
-#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef _WIN32
@@ -49,8 +48,6 @@
#define O_BINARY 0
#endif // _WIN32
-#include <cstring>
-
#include <cassert>
#include <limits>
#include <map>
@@ -274,6 +271,7 @@
MinidumpContext::MinidumpContext(Minidump* minidump)
: MinidumpStream(minidump),
+ context_flags_(0),
context_() {
}
@@ -289,233 +287,334 @@
FreeContext();
// First, figure out what type of CPU this context structure is for.
- u_int32_t context_flags;
- if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
- BPLOG(ERROR) << "MinidumpContext could not read context flags";
- return false;
- }
- if (minidump_->swap())
- Swap(&context_flags);
+ // For some reason, the AMD64 Context doesn't have context_flags
+ // at the beginning of the structure, so special case it here.
+ if (expected_size == sizeof(MDRawContextAMD64)) {
+ BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
+
+ scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
+ if (!minidump_->ReadBytes(context_amd64.get(),
+ sizeof(MDRawContextAMD64))) {
+ BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
+ return false;
+ }
- u_int32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
+ if (minidump_->swap())
+ Swap(&context_amd64->context_flags);
- // Allocate the context structure for the correct CPU and fill it. The
- // casts are slightly unorthodox, but it seems better to do that than to
- // maintain a separate pointer for each type of CPU context structure
- // when only one of them will be used.
- switch (cpu_type) {
- case MD_CONTEXT_X86: {
- if (expected_size != sizeof(MDRawContextX86)) {
- BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
- expected_size << " != " << sizeof(MDRawContextX86);
- return false;
- }
+ u_int32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
- scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
+ if (cpu_type != MD_CONTEXT_AMD64) {
+ //TODO: fall through to switch below?
+ // need a Tell method to be able to SeekSet back to beginning
+ // http://code.google.com/p/google-breakpad/issues/detail?id=224
+ BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
+ return false;
+ }
- // Set the context_flags member, which has already been read, and
- // read the rest of the structure beginning with the first member
- // after context_flags.
- context_x86->context_flags = context_flags;
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
+ return false;
+ }
- size_t flags_size = sizeof(context_x86->context_flags);
- u_int8_t* context_after_flags =
- reinterpret_cast<u_int8_t*>(context_x86.get()) + flags_size;
- if (!minidump_->ReadBytes(context_after_flags,
- sizeof(MDRawContextX86) - flags_size)) {
- BPLOG(ERROR) << "MinidumpContext could not read x86 context";
- return false;
- }
+ // Normalize the 128-bit types in the dump.
+ // Since this is AMD64, by definition, the values are little-endian.
+ for (unsigned int vr_index = 0;
+ vr_index < MD_CONTEXT_AMD64_VR_COUNT;
+ ++vr_index)
+ Normalize128(&context_amd64->vector_register[vr_index], false);
- // Do this after reading the entire MDRawContext structure because
- // GetSystemInfo may seek minidump to a new position.
- if (!CheckAgainstSystemInfo(cpu_type)) {
- BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
- return false;
- }
+ if (minidump_->swap()) {
+ Swap(&context_amd64->p1_home);
+ Swap(&context_amd64->p2_home);
+ Swap(&context_amd64->p3_home);
+ Swap(&context_amd64->p4_home);
+ Swap(&context_amd64->p5_home);
+ Swap(&context_amd64->p6_home);
+ // context_flags is already swapped
+ Swap(&context_amd64->mx_csr);
+ Swap(&context_amd64->cs);
+ Swap(&context_amd64->ds);
+ Swap(&context_amd64->es);
+ Swap(&context_amd64->fs);
+ Swap(&context_amd64->ss);
+ Swap(&context_amd64->eflags);
+ Swap(&context_amd64->dr0);
+ Swap(&context_amd64->dr1);
+ Swap(&context_amd64->dr2);
+ Swap(&context_amd64->dr3);
+ Swap(&context_amd64->dr6);
+ Swap(&context_amd64->dr7);
+ Swap(&context_amd64->rax);
+ Swap(&context_amd64->rcx);
+ Swap(&context_amd64->rdx);
+ Swap(&context_amd64->rbx);
+ Swap(&context_amd64->rsp);
+ Swap(&context_amd64->rbp);
+ Swap(&context_amd64->rsi);
+ Swap(&context_amd64->rdi);
+ Swap(&context_amd64->r8);
+ Swap(&context_amd64->r9);
+ Swap(&context_amd64->r10);
+ Swap(&context_amd64->r11);
+ Swap(&context_amd64->r12);
+ Swap(&context_amd64->r13);
+ Swap(&context_amd64->r14);
+ Swap(&context_amd64->r15);
+ Swap(&context_amd64->rip);
+ //FIXME: I'm not sure what actually determines
+ // which member of the union {flt_save, sse_registers}
+ // is valid. We're not currently using either,
+ // but it would be good to have them swapped properly.
- if (minidump_->swap()) {
- // context_x86->context_flags was already swapped.
- Swap(&context_x86->dr0);
- Swap(&context_x86->dr1);
- Swap(&context_x86->dr2);
- Swap(&context_x86->dr3);
- Swap(&context_x86->dr6);
- Swap(&context_x86->dr7);
- Swap(&context_x86->float_save.control_word);
- Swap(&context_x86->float_save.status_word);
- Swap(&context_x86->float_save.tag_word);
- Swap(&context_x86->float_save.error_offset);
- Swap(&context_x86->float_save.error_selector);
- Swap(&context_x86->float_save.data_offset);
- Swap(&context_x86->float_save.data_selector);
- // context_x86->float_save.register_area[] contains 8-bit quantities
- // and does not need to be swapped.
- Swap(&context_x86->float_save.cr0_npx_state);
- Swap(&context_x86->gs);
- Swap(&context_x86->fs);
- Swap(&context_x86->es);
- Swap(&context_x86->ds);
- Swap(&context_x86->edi);
- Swap(&context_x86->esi);
- Swap(&context_x86->ebx);
- Swap(&context_x86->edx);
- Swap(&context_x86->ecx);
- Swap(&context_x86->eax);
- Swap(&context_x86->ebp);
- Swap(&context_x86->eip);
- Swap(&context_x86->cs);
- Swap(&context_x86->eflags);
- Swap(&context_x86->esp);
- Swap(&context_x86->ss);
- // context_x86->extended_registers[] contains 8-bit quantities and
- // does not need to be swapped.
- }
+ for (unsigned int vr_index = 0;
+ vr_index < MD_CONTEXT_AMD64_VR_COUNT;
+ ++vr_index)
+ Swap(&context_amd64->vector_register[vr_index]);
+ Swap(&context_amd64->vector_control);
+ Swap(&context_amd64->debug_control);
+ Swap(&context_amd64->last_branch_to_rip);
+ Swap(&context_amd64->last_branch_from_rip);
+ Swap(&context_amd64->last_exception_to_rip);
+ Swap(&context_amd64->last_exception_from_rip);
+ }
+
+ context_flags_ = context_amd64->context_flags;
+
+ context_.amd64 = context_amd64.release();
+ }
+ else {
+ u_int32_t context_flags;
+ if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
+ BPLOG(ERROR) << "MinidumpContext could not read context flags";
+ return false;
+ }
+ if (minidump_->swap())
+ Swap(&context_flags);
- context_.x86 = context_x86.release();
+ u_int32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
- break;
- }
+ // Allocate the context structure for the correct CPU and fill it. The
+ // casts are slightly unorthodox, but it seems better to do that than to
+ // maintain a separate pointer for each type of CPU context structure
+ // when only one of them will be used.
+ switch (cpu_type) {
+ case MD_CONTEXT_X86: {
+ if (expected_size != sizeof(MDRawContextX86)) {
+ BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextX86);
+ return false;
+ }
- case MD_CONTEXT_PPC: {
- if (expected_size != sizeof(MDRawContextPPC)) {
- BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
- expected_size << " != " << sizeof(MDRawContextPPC);
- return false;
- }
+ scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
- scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_x86->context_flags = context_flags;
- // Set the context_flags member, which has already been read, and
- // read the rest of the structure beginning with the first member
- // after context_flags.
- context_ppc->context_flags = context_flags;
+ size_t flags_size = sizeof(context_x86->context_flags);
+ u_int8_t* context_after_flags =
+ reinterpret_cast<u_int8_t*>(context_x86.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextX86) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read x86 context";
+ return false;
+ }
- size_t flags_size = sizeof(context_ppc->context_flags);
- u_int8_t* context_after_flags =
- reinterpret_cast<u_int8_t*>(context_ppc.get()) + flags_size;
- if (!minidump_->ReadBytes(context_after_flags,
- sizeof(MDRawContextPPC) - flags_size)) {
- BPLOG(ERROR) << "MinidumpContext could not read ppc context";
- return false;
- }
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
+ return false;
+ }
- // Do this after reading the entire MDRawContext structure because
- // GetSystemInfo may seek minidump to a new position.
- if (!CheckAgainstSystemInfo(cpu_type)) {
- BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
- return false;
- }
+ if (minidump_->swap()) {
+ // context_x86->context_flags was already swapped.
+ Swap(&context_x86->dr0);
+ Swap(&context_x86->dr1);
+ Swap(&context_x86->dr2);
+ Swap(&context_x86->dr3);
+ Swap(&context_x86->dr6);
+ Swap(&context_x86->dr7);
+ Swap(&context_x86->float_save.control_word);
+ Swap(&context_x86->float_save.status_word);
+ Swap(&context_x86->float_save.tag_word);
+ Swap(&context_x86->float_save.error_offset);
+ Swap(&context_x86->float_save.error_selector);
+ Swap(&context_x86->float_save.data_offset);
+ Swap(&context_x86->float_save.data_selector);
+ // context_x86->float_save.register_area[] contains 8-bit quantities
+ // and does not need to be swapped.
+ Swap(&context_x86->float_save.cr0_npx_state);
+ Swap(&context_x86->gs);
+ Swap(&context_x86->fs);
+ Swap(&context_x86->es);
+ Swap(&context_x86->ds);
+ Swap(&context_x86->edi);
+ Swap(&context_x86->esi);
+ Swap(&context_x86->ebx);
+ Swap(&context_x86->edx);
+ Swap(&context_x86->ecx);
+ Swap(&context_x86->eax);
+ Swap(&context_x86->ebp);
+ Swap(&context_x86->eip);
+ Swap(&context_x86->cs);
+ Swap(&context_x86->eflags);
+ Swap(&context_x86->esp);
+ Swap(&context_x86->ss);
+ // context_x86->extended_registers[] contains 8-bit quantities and
+ // does not need to be swapped.
+ }
- // Normalize the 128-bit types in the dump.
- // Since this is PowerPC, by definition, the values are big-endian.
- for (unsigned int vr_index = 0;
- vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
- ++vr_index) {
- Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
+ context_.x86 = context_x86.release();
+
+ break;
}
- if (minidump_->swap()) {
- // context_ppc->context_flags was already swapped.
- Swap(&context_ppc->srr0);
- Swap(&context_ppc->srr1);
- for (unsigned int gpr_index = 0;
- gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
- ++gpr_index) {
- Swap(&context_ppc->gpr[gpr_index]);
+ case MD_CONTEXT_PPC: {
+ if (expected_size != sizeof(MDRawContextPPC)) {
+ BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextPPC);
+ return false;
+ }
+
+ scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_ppc->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_ppc->context_flags);
+ u_int8_t* context_after_flags =
+ reinterpret_cast<u_int8_t*>(context_ppc.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextPPC) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read ppc context";
+ return false;
}
- Swap(&context_ppc->cr);
- Swap(&context_ppc->xer);
- Swap(&context_ppc->lr);
- Swap(&context_ppc->ctr);
- Swap(&context_ppc->mq);
- Swap(&context_ppc->vrsave);
- for (unsigned int fpr_index = 0;
- fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
- ++fpr_index) {
- Swap(&context_ppc->float_save.fpregs[fpr_index]);
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
+ return false;
}
- // Don't swap context_ppc->float_save.fpscr_pad because it is only
- // used for padding.
- Swap(&context_ppc->float_save.fpscr);
+
+ // Normalize the 128-bit types in the dump.
+ // Since this is PowerPC, by definition, the values are big-endian.
for (unsigned int vr_index = 0;
vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
++vr_index) {
- Swap(&context_ppc->vector_save.save_vr[vr_index]);
+ Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
}
- Swap(&context_ppc->vector_save.save_vscr);
- // Don't swap the padding fields in vector_save.
- Swap(&context_ppc->vector_save.save_vrvalid);
- }
- context_.ppc = context_ppc.release();
+ if (minidump_->swap()) {
+ // context_ppc->context_flags was already swapped.
+ Swap(&context_ppc->srr0);
+ Swap(&context_ppc->srr1);
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
+ ++gpr_index) {
+ Swap(&context_ppc->gpr[gpr_index]);
+ }
+ Swap(&context_ppc->cr);
+ Swap(&context_ppc->xer);
+ Swap(&context_ppc->lr);
+ Swap(&context_ppc->ctr);
+ Swap(&context_ppc->mq);
+ Swap(&context_ppc->vrsave);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_ppc->float_save.fpregs[fpr_index]);
+ }
+ // Don't swap context_ppc->float_save.fpscr_pad because it is only
+ // used for padding.
+ Swap(&context_ppc->float_save.fpscr);
+ for (unsigned int vr_index = 0;
+ vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
+ ++vr_index) {
+ Swap(&context_ppc->vector_save.save_vr[vr_index]);
+ }
+ Swap(&context_ppc->vector_save.save_vscr);
+ // Don't swap the padding fields in vector_save.
+ Swap(&context_ppc->vector_save.save_vrvalid);
+ }
- break;
- }
+ context_.ppc = context_ppc.release();
- case MD_CONTEXT_SPARC: {
- if (expected_size != sizeof(MDRawContextSPARC)) {
- BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
- expected_size << " != " << sizeof(MDRawContextSPARC);
- return false;
+ break;
}
- scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
+ case MD_CONTEXT_SPARC: {
+ if (expected_size != sizeof(MDRawContextSPARC)) {
+ BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextSPARC);
+ return false;
+ }
- // Set the context_flags member, which has already been read, and
- // read the rest of the structure beginning with the first member
- // after context_flags.
- context_sparc->context_flags = context_flags;
-
- size_t flags_size = sizeof(context_sparc->context_flags);
- u_int8_t* context_after_flags =
- reinterpret_cast<u_int8_t*>(context_sparc.get()) + flags_size;
- if (!minidump_->ReadBytes(context_after_flags,
- sizeof(MDRawContextSPARC) - flags_size)) {
- BPLOG(ERROR) << "MinidumpContext could not read sparc context";
- return false;
- }
+ scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
- // Do this after reading the entire MDRawContext structure because
- // GetSystemInfo may seek minidump to a new position.
- if (!CheckAgainstSystemInfo(cpu_type)) {
- BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
- return false;
- }
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_sparc->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_sparc->context_flags);
+ u_int8_t* context_after_flags =
+ reinterpret_cast<u_int8_t*>(context_sparc.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextSPARC) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read sparc context";
+ return false;
+ }
- if (minidump_->swap()) {
- // context_sparc->context_flags was already swapped.
- for (unsigned int gpr_index = 0;
- gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
- ++gpr_index) {
- Swap(&context_sparc->g_r[gpr_index]);
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
+ return false;
}
- Swap(&context_sparc->ccr);
- Swap(&context_sparc->pc);
- Swap(&context_sparc->npc);
- Swap(&context_sparc->y);
- Swap(&context_sparc->asi);
- Swap(&context_sparc->fprs);
- for (unsigned int fpr_index = 0;
- fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
- ++fpr_index) {
- Swap(&context_sparc->float_save.regs[fpr_index]);
+
+ if (minidump_->swap()) {
+ // context_sparc->context_flags was already swapped.
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
+ ++gpr_index) {
+ Swap(&context_sparc->g_r[gpr_index]);
+ }
+ Swap(&context_sparc->ccr);
+ Swap(&context_sparc->pc);
+ Swap(&context_sparc->npc);
+ Swap(&context_sparc->y);
+ Swap(&context_sparc->asi);
+ Swap(&context_sparc->fprs);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_sparc->float_save.regs[fpr_index]);
+ }
+ Swap(&context_sparc->float_save.filler);
+ Swap(&context_sparc->float_save.fsr);
}
- Swap(&context_sparc->float_save.filler);
- Swap(&context_sparc->float_save.fsr);
- }
- context_.ctx_sparc = context_sparc.release();
+ context_.ctx_sparc = context_sparc.release();
- break;
- }
+ break;
+ }
- default: {
- // Unknown context type
- BPLOG(ERROR) << "MinidumpContext unknown context type " <<
- HexString(cpu_type);
- return false;
- break;
+ default: {
+ // Unknown context type
+ BPLOG(ERROR) << "MinidumpContext unknown context type " <<
+ HexString(cpu_type);
+ return false;
+ break;
+ }
}
+ context_flags_ = context_flags;
}
valid_ = true;
@@ -530,7 +629,7 @@
return 0;
}
- return context_.base->context_flags & MD_CONTEXT_CPU_MASK;
+ return context_flags_ & MD_CONTEXT_CPU_MASK;
}
@@ -553,6 +652,15 @@
return context_.ppc;
}
+const MDRawContextAMD64* MinidumpContext::GetContextAMD64() const {
+ if (GetContextCPU() != MD_CONTEXT_AMD64) {
+ BPLOG(ERROR) << "MinidumpContext cannot get amd64 context";
+ return NULL;
+ }
+
+ return context_.amd64;
+}
+
const MDRawContextSPARC* MinidumpContext::GetContextSPARC() const {
if (GetContextCPU() != MD_CONTEXT_SPARC) {
BPLOG(ERROR) << "MinidumpContext cannot get sparc context";
@@ -572,6 +680,10 @@
delete context_.ppc;
break;
+ case MD_CONTEXT_AMD64:
+ delete context_.amd64;
+ break;
+
case MD_CONTEXT_SPARC:
delete context_.ctx_sparc;
break;
@@ -583,6 +695,7 @@
break;
}
+ context_flags_ = 0;
context_.base = NULL;
}
@@ -614,7 +727,8 @@
switch (context_cpu_type) {
case MD_CONTEXT_X86:
if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
- system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64) {
+ system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
+ system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
return_value = true;
}
break;
@@ -624,6 +738,11 @@
return_value = true;
break;
+ case MD_CONTEXT_AMD64:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
+ return_value = true;
+ break;
+
case MD_CONTEXT_SPARC:
if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
return_value = true;
@@ -731,7 +850,7 @@
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",
@@ -739,7 +858,7 @@
// 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);
@@ -748,6 +867,60 @@
break;
}
+ case MD_CONTEXT_AMD64: {
+ const MDRawContextAMD64* context_amd64 = GetContextAMD64();
+ printf("MDRawContextAMD64\n");
+ printf(" p1_home = 0x%" PRIx64 "\n",
+ context_amd64->p1_home);
+ printf(" p2_home = 0x%" PRIx64 "\n",
+ context_amd64->p2_home);
+ printf(" p3_home = 0x%" PRIx64 "\n",
+ context_amd64->p3_home);
+ printf(" p4_home = 0x%" PRIx64 "\n",
+ context_amd64->p4_home);
+ printf(" p5_home = 0x%" PRIx64 "\n",
+ context_amd64->p5_home);
+ printf(" p6_home = 0x%" PRIx64 "\n",
+ context_amd64->p6_home);
+ printf(" context_flags = 0x%x\n",
+ context_amd64->context_flags);
+ printf(" mx_csr = 0x%x\n",
+ context_amd64->mx_csr);
+ printf(" cs = 0x%x\n", context_amd64->cs);
+ printf(" ds = 0x%x\n", context_amd64->ds);
+ printf(" es = 0x%x\n", context_amd64->es);
+ printf(" fs = 0x%x\n", context_amd64->fs);
+ 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%" 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;
+ }
+
case MD_CONTEXT_SPARC: {
const MDRawContextSPARC* context_sparc = GetContextSPARC();
printf("MDRawContextSPARC\n");
@@ -756,25 +929,25 @@
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;
}
@@ -1092,8 +1265,8 @@
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);
@@ -1297,6 +1470,7 @@
MinidumpModule::MinidumpModule(Minidump* minidump)
: MinidumpObject(minidump),
module_valid_(false),
+ has_debug_info_(false),
module_(),
name_(NULL),
cv_record_(NULL),
@@ -1323,6 +1497,7 @@
misc_record_ = NULL;
module_valid_ = false;
+ has_debug_info_ = false;
valid_ = false;
if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
@@ -1383,6 +1558,9 @@
return false;
}
+ // At this point, we have enough info for the module to be valid.
+ valid_ = true;
+
// CodeView and miscellaneous debug records are only required if the
// module indicates that they exist.
if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
@@ -1397,7 +1575,7 @@
return false;
}
- valid_ = true;
+ has_debug_info_ = true;
return true;
}
@@ -1418,6 +1596,9 @@
return "";
}
+ if (!has_debug_info_)
+ return "";
+
MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
if (!minidump_system_info) {
BPLOG(ERROR) << "MinidumpModule code_identifier requires "
@@ -1474,6 +1655,9 @@
return "";
}
+ if (!has_debug_info_)
+ return "";
+
string file;
// Prefer the CodeView record if present.
if (cv_record_) {
@@ -1550,6 +1734,9 @@
return "";
}
+ if (!has_debug_info_)
+ return "";
+
string identifier;
// Use the CodeView record if present.
@@ -1863,7 +2050,7 @@
}
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);
@@ -2092,15 +2279,20 @@
++module_index) {
MinidumpModule* module = &(*modules)[module_index];
- if (!module->ReadAuxiliaryData()) {
- BPLOG(ERROR) << "MinidumpModuleList could not read module auxiliary "
- "data for module " <<
+ // ReadAuxiliaryData fails if any data that the module indicates should
+ // exist is missing, but we treat some such cases as valid anyway. See
+ // issue #222: if a debugging record is of a format that's too large to
+ // handle, it shouldn't render the entire dump invalid. Check module
+ // validity before giving up.
+ if (!module->ReadAuxiliaryData() && !module->valid()) {
+ BPLOG(ERROR) << "MinidumpModuleList could not read required module "
+ "auxiliary data for module " <<
module_index << "/" << module_count;
return false;
}
// It is safe to use module->code_file() after successfully calling
- // module->ReadAuxiliaryData.
+ // module->ReadAuxiliaryData or noting that the module is valid.
u_int64_t base_address = module->base_address();
u_int64_t module_size = module->size();
@@ -2415,7 +2607,7 @@
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);
@@ -2545,16 +2737,16 @@
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]);
}
@@ -2698,6 +2890,10 @@
cpu = "ppc";
break;
+ case MD_CPU_ARCHITECTURE_SPARC:
+ cpu = "sparc";
+ break;
+
default:
BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
HexString(system_info_.processor_architecture);
@@ -3252,7 +3448,7 @@
strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct);
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;
Modified: trunk/google-breakpad/src/processor/minidump_processor.cc
==============================================================================
--- trunk/google-breakpad/src/processor/minidump_processor.cc (original)
+++ trunk/google-breakpad/src/processor/minidump_processor.cc Sun Oct 19 13:26:38 2008
@@ -258,8 +258,14 @@
return false;
switch (raw_system_info->processor_architecture) {
- case MD_CPU_ARCHITECTURE_X86: {
- info->cpu = "x86";
+ case MD_CPU_ARCHITECTURE_X86:
+ case MD_CPU_ARCHITECTURE_AMD64: {
+ if (raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_X86)
+ info->cpu = "x86";
+ else
+ info->cpu = "amd64";
+
const string *cpu_vendor = system_info->GetCPUVendor();
if (cpu_vendor) {
info->cpu_info = *cpu_vendor;
Modified: trunk/google-breakpad/src/processor/minidump_stackwalk.cc
==============================================================================
--- trunk/google-breakpad/src/processor/minidump_stackwalk.cc (original)
+++ trunk/google-breakpad/src/processor/minidump_stackwalk.cc Sun Oct 19 13:26:38 2008
@@ -71,6 +71,7 @@
using google_breakpad::StackFramePPC;
using google_breakpad::StackFrameSPARC;
using google_breakpad::StackFrameX86;
+using google_breakpad::StackFrameAMD64;
// Separator character for machine readable output.
static const char kOutputSeparator = '|';
@@ -123,18 +124,19 @@
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;
@@ -168,6 +170,16 @@
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
+ } else if (cpu == "amd64") {
+ const StackFrameAMD64 *frame_amd64 =
+ reinterpret_cast<const StackFrameAMD64*>(frame);
+
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
+ sequence = PrintRegister("rip", frame_amd64->context.rip, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
+ sequence = PrintRegister("rsp", frame_amd64->context.rsp, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
+ sequence = PrintRegister("rbp", frame_amd64->context.rbp, sequence);
} else if (cpu == "sparc") {
const StackFrameSPARC *frame_sparc =
reinterpret_cast<const StackFrameSPARC*>(frame);
@@ -179,7 +191,6 @@
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
}
-
printf("\n");
}
}
@@ -206,35 +217,36 @@
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");
}
@@ -259,7 +271,7 @@
++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(),
@@ -289,7 +301,7 @@
++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(),
@@ -324,7 +336,7 @@
// 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");
}
@@ -377,7 +389,7 @@
// 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 {
Modified: trunk/google-breakpad/src/processor/simple_symbol_supplier.cc
==============================================================================
--- trunk/google-breakpad/src/processor/simple_symbol_supplier.cc (original)
+++ trunk/google-breakpad/src/processor/simple_symbol_supplier.cc Sun Oct 19 13:26:38 2008
@@ -38,7 +38,6 @@
#include <algorithm>
#include <cassert>
-#include <algorithm>
#include "processor/simple_symbol_supplier.h"
#include "google_breakpad/processor/code_module.h"
Modified: trunk/google-breakpad/src/processor/stackwalker.cc
==============================================================================
--- trunk/google-breakpad/src/processor/stackwalker.cc (original)
+++ trunk/google-breakpad/src/processor/stackwalker.cc Sun Oct 19 13:26:38 2008
@@ -51,6 +51,7 @@
#include "processor/stackwalker_ppc.h"
#include "processor/stackwalker_sparc.h"
#include "processor/stackwalker_x86.h"
+#include "processor/stackwalker_amd64.h"
namespace google_breakpad {
@@ -164,6 +165,13 @@
memory, modules, supplier,
resolver);
break;
+
+ case MD_CONTEXT_AMD64:
+ cpu_stackwalker = new StackwalkerAMD64(system_info,
+ context->GetContextAMD64(),
+ memory, modules, supplier,
+ resolver);
+ break;
case MD_CONTEXT_SPARC:
cpu_stackwalker = new StackwalkerSPARC(system_info,
Added: trunk/google-breakpad/src/processor/stackwalker_amd64.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/processor/stackwalker_amd64.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,131 @@
+// Copyright (c) 2007, 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.
+
+// stackwalker_amd64.cc: amd64-specific stackwalker.
+//
+// See stackwalker_amd64.h for documentation.
+//
+// Author: Mark Mentovai, Ted Mielczarek
+
+
+#include "processor/stackwalker_amd64.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+
+StackwalkerAMD64::StackwalkerAMD64(const SystemInfo *system_info,
+ const MDRawContextAMD64 *context,
+ MemoryRegion *memory,
+ const CodeModules *modules,
+ SymbolSupplier *supplier,
+ SourceLineResolverInterface *resolver)
+ : Stackwalker(system_info, memory, modules, supplier, resolver),
+ context_(context) {
+}
+
+
+StackFrame* StackwalkerAMD64::GetContextFrame() {
+ if (!context_ || !memory_) {
+ BPLOG(ERROR) << "Can't get context frame without context or memory";
+ return NULL;
+ }
+
+ StackFrameAMD64 *frame = new StackFrameAMD64();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL;
+ frame->instruction = frame->context.rip;
+
+ return frame;
+}
+
+
+StackFrame* StackwalkerAMD64::GetCallerFrame(
+ const CallStack *stack,
+ const vector< linked_ptr<StackFrameInfo> > &stack_frame_info) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64*>(
+ stack->frames()->back());
+
+ //FIXME: this pretty much doesn't work at all due to FPO
+ // being enabled by default.
+ // Brain-dead stackwalking:
+ // %rip_new = *(%rbp_old + 8)
+ // %rsp_new = %rbp_old + 16
+ // %rbp_new = *(%rbp_old)
+
+ // A caller frame must reside higher in memory than its callee frames.
+ // Anything else is an error, or an indication that we've reached the
+ // end of the stack.
+ u_int64_t stack_pointer = last_frame->context.rbp + 16;
+ if (stack_pointer <= last_frame->context.rsp) {
+ return NULL;
+ }
+
+ u_int64_t instruction;
+ if (!memory_->GetMemoryAtAddress(last_frame->context.rbp + 8,
+ &instruction) ||
+ instruction <= 1) {
+ return NULL;
+ }
+
+ u_int64_t stack_base;
+ if (!memory_->GetMemoryAtAddress(last_frame->context.rbp,
+ &stack_base) ||
+ stack_base <= 1) {
+ return NULL;
+ }
+
+ StackFrameAMD64 *frame = new StackFrameAMD64();
+
+ frame->context = last_frame->context;
+ frame->context.rip = instruction;
+ frame->context.rsp = stack_pointer;
+ frame->context.rbp = stack_base;
+ frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP;
+
+ frame->instruction = frame->context.rip - 1;
+
+ return frame;
+}
+
+
+} // namespace google_breakpad
Added: trunk/google-breakpad/src/processor/stackwalker_amd64.h
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/processor/stackwalker_amd64.h Sun Oct 19 13:26:38 2008
@@ -0,0 +1,80 @@
+// Copyright (c) 2007, 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.
+
+// stackwalker_amd64.h: amd64-specific stackwalker.
+//
+// Provides stack frames given amd64 register context and a memory region
+// corresponding to a amd64 stack.
+//
+// Author: Mark Mentovai, Ted Mielczarek
+
+
+#ifndef PROCESSOR_STACKWALKER_AMD64_H__
+#define PROCESSOR_STACKWALKER_AMD64_H__
+
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerAMD64 : public Stackwalker {
+ public:
+ // context is a amd64 context object that gives access to amd64-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerAMD64(const SystemInfo *system_info,
+ const MDRawContextAMD64 *context,
+ MemoryRegion *memory,
+ const CodeModules *modules,
+ SymbolSupplier *supplier,
+ SourceLineResolverInterface *resolver);
+
+ private:
+ // Implementation of Stackwalker, using amd64 context (stack pointer in %rsp,
+ // stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp))
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(
+ const CallStack *stack,
+ const vector< linked_ptr<StackFrameInfo> > &stack_frame_info);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextAMD64 *context_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_AMD64_H__
Modified: trunk/google-breakpad/src/processor/stackwalker_selftest.cc
==============================================================================
--- trunk/google-breakpad/src/processor/stackwalker_selftest.cc (original)
+++ trunk/google-breakpad/src/processor/stackwalker_selftest.cc Sun Oct 19 13:26:38 2008
@@ -345,7 +345,7 @@
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);
Modified: trunk/google-breakpad/src/tools/linux/dump_syms/Makefile
==============================================================================
--- trunk/google-breakpad/src/tools/linux/dump_syms/Makefile (original)
+++ trunk/google-breakpad/src/tools/linux/dump_syms/Makefile Sun Oct 19 13:26:38 2008
@@ -23,7 +23,7 @@
file_id.o:../../../common/linux/file_id.cc
$(CXX) $(CXXFLAGS) -c $^
-md5.o:../../../common/linux/md5.c
+md5.o:../../../common/md5.c
$(CC) $(CXXFLAGS) -c $^
clean:
Modified: trunk/google-breakpad/src/tools/linux/symupload/Makefile
==============================================================================
--- trunk/google-breakpad/src/tools/linux/symupload/Makefile (original)
+++ trunk/google-breakpad/src/tools/linux/symupload/Makefile Sun Oct 19 13:26:38 2008
@@ -12,10 +12,10 @@
SYM_UPLOAD_OBJ=sym_upload.o http_upload.o
minidump_upload:$(DUMP_UPLOAD_OBJ)
- $(CXX) $(CXXFLAGS) `curl-config --libs` -o $@ $^
+ $(CXX) $(CXXFLAGS) -ldl -o $@ $^
sym_upload:$(SYM_UPLOAD_OBJ)
- $(CXX) $(CXXFLAGS) `curl-config --libs` -o $@ $^
+ $(CXX) $(CXXFLAGS) -ldl -o $@ $^
http_upload.o:../../../common/linux/http_upload.cc
$(CXX) $(CXXFLAGS) `curl-config --cflags` -c $^
Modified: trunk/google-breakpad/src/tools/linux/symupload/minidump_upload.cc
==============================================================================
--- trunk/google-breakpad/src/tools/linux/symupload/minidump_upload.cc (original)
+++ trunk/google-breakpad/src/tools/linux/symupload/minidump_upload.cc Sun Oct 19 13:26:38 2008
@@ -59,19 +59,20 @@
parameters["ver"] = options->version;
// Send it
- std::string response;
+ std::string response, error;
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
parameters,
options->minidumpPath,
"upload_file_minidump",
options->proxy,
options->proxy_user_pwd,
- &response);
+ &response,
+ &error);
if (success) {
printf("Successfully sent the minidump file.\n");
} else {
- printf("Failed to send minidump\n");
+ printf("Failed to send minidump: %s\n", error.c_str());
printf("Response:\n");
printf("%s\n", response.c_str());
}
Modified: trunk/google-breakpad/src/tools/linux/symupload/sym_upload.cc
==============================================================================
--- trunk/google-breakpad/src/tools/linux/symupload/sym_upload.cc (original)
+++ trunk/google-breakpad/src/tools/linux/symupload/sym_upload.cc Sun Oct 19 13:26:38 2008
@@ -137,19 +137,20 @@
parameters["debug_file"] = module_parts[4];
parameters["code_file"] = module_parts[4];
parameters["debug_identifier"] = compacted_id;
- std::string response;
+ std::string response, error;
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
parameters,
options->symbolsPath,
"symbol_file",
options->proxy,
options->proxy_user_pwd,
- &response);
+ &response,
+ &error);
if (success) {
printf("Successfully sent the symbol file.\n");
} else {
- printf("Failed to send symbol file.\n");
+ printf("Failed to send symbol file: %s\n", error.c_str());
printf("Response:\n");
printf("%s\n", response.c_str());
}
Modified: trunk/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
==============================================================================
--- trunk/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj (original)
+++ trunk/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj Sun Oct 19 13:26:38 2008
@@ -43,6 +43,12 @@
9BE650B50B52FE3000611104 /* macho_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE650AF0B52FE3000611104 /* macho_id.h */; };
9BE650B60B52FE3000611104 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650B00B52FE3000611104 /* macho_walker.cc */; };
9BE650B70B52FE3000611104 /* macho_walker.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE650B10B52FE3000611104 /* macho_walker.h */; };
+ F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE20E8ABCA600E953AD /* bytereader.cc */; };
+ F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */; };
+ F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */; };
+ FD6625CD0CF4D45C004AC844 /* stackwalker_amd64.cc in Sources */ = {isa = PBXBuildFile; fileRef = FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */; };
+ FD8EDEAE0CADDAD400A5EDF1 /* stackwalker_sparc.cc in Sources */ = {isa = PBXBuildFile; fileRef = FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */; };
+ FD8EDEAF0CADDAD400A5EDF1 /* stackwalker_sparc.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -69,6 +75,7 @@
9BE650B70B52FE3000611104 /* macho_walker.h in CopyFiles */,
9B44619E0B66C66B00BBB817 /* system_info.h in CopyFiles */,
557800410BE1F28500EC23E0 /* macho_utilities.h in CopyFiles */,
+ FD8EDEAF0CADDAD400A5EDF1 /* stackwalker_sparc.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@@ -123,6 +130,13 @@
9BE650AF0B52FE3000611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
9BE650B00B52FE3000611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
9BE650B10B52FE3000611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
+ FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_amd64.cc; path = ../../../processor/stackwalker_amd64.cc; sourceTree = SOURCE_ROOT; };
+ FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_amd64.h; path = ../../../processor/stackwalker_amd64.h; sourceTree = SOURCE_ROOT; };
+ FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_sparc.cc; path = ../../../processor/stackwalker_sparc.cc; sourceTree = SOURCE_ROOT; };
+ FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = stackwalker_sparc.h; path = ../../../processor/stackwalker_sparc.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -140,6 +154,7 @@
08FB7794FE84155DC02AAC07 /* crash_report */ = {
isa = PBXGroup;
children = (
+ F9C7ECE10E8ABC7F00E953AD /* DWARF */,
5578003E0BE1F28500EC23E0 /* macho_utilities.cc */,
5578003F0BE1F28500EC23E0 /* macho_utilities.h */,
9BDF192D0B1BC15D00F8391B /* dump_syms.h */,
@@ -240,6 +255,10 @@
9BDF17530B1B8BF900F8391B /* stackwalker.cc */,
9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */,
9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */,
+ FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */,
+ FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */,
+ FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */,
+ FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */,
);
name = processor;
sourceTree = "<group>";
@@ -257,6 +276,16 @@
name = common;
sourceTree = "<group>";
};
+ F9C7ECE10E8ABC7F00E953AD /* DWARF */ = {
+ isa = PBXGroup;
+ children = (
+ F9C7ECE20E8ABCA600E953AD /* bytereader.cc */,
+ F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */,
+ F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */,
+ );
+ name = DWARF;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -284,9 +313,11 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "crash_report" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* crash_report */;
projectDirPath = "";
+ projectRoot = "";
targets = (
8DD76F960486AA7600D96B5E /* crash_report */,
);
@@ -316,6 +347,11 @@
9BE650B60B52FE3000611104 /* macho_walker.cc in Sources */,
557800400BE1F28500EC23E0 /* macho_utilities.cc in Sources */,
8B40BDC00C0638E4009535AF /* logging.cc in Sources */,
+ FD8EDEAE0CADDAD400A5EDF1 /* stackwalker_sparc.cc in Sources */,
+ FD6625CD0CF4D45C004AC844 /* stackwalker_amd64.cc in Sources */,
+ F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */,
+ F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */,
+ F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
==============================================================================
--- trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj (original)
+++ trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj Sun Oct 19 13:26:38 2008
@@ -8,17 +8,15 @@
/* Begin PBXBuildFile section */
5578008B0BE1F3AB00EC23E0 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 557800890BE1F3AB00EC23E0 /* macho_utilities.cc */; };
- 5578008C0BE1F3AB00EC23E0 /* macho_utilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5578008A0BE1F3AB00EC23E0 /* macho_utilities.h */; };
8DD76F9A0486AA7600D96B5E /* dump_syms.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* dump_syms.mm */; settings = {ATTRIBUTES = (); }; };
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
- 9BDF186F0B1BB43700F8391B /* dump_syms.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BDF186D0B1BB43700F8391B /* dump_syms.h */; };
- 9BDF18700B1BB43700F8391B /* dump_syms_tool.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF186E0B1BB43700F8391B /* dump_syms_tool.m */; };
+ 9BDF18700B1BB43700F8391B /* dump_syms_tool.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */; };
9BE650470B52F6D800611104 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650410B52F6D800611104 /* file_id.cc */; };
- 9BE650480B52F6D800611104 /* file_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE650420B52F6D800611104 /* file_id.h */; };
9BE650490B52F6D800611104 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650430B52F6D800611104 /* macho_id.cc */; };
- 9BE6504A0B52F6D800611104 /* macho_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE650440B52F6D800611104 /* macho_id.h */; };
9BE6504B0B52F6D800611104 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650450B52F6D800611104 /* macho_walker.cc */; };
- 9BE6504C0B52F6D800611104 /* macho_walker.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE650460B52F6D800611104 /* macho_walker.h */; };
+ F95B42320E0E22D100DBDE83 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422C0E0E22D100DBDE83 /* bytereader.cc */; };
+ F95B42330E0E22D100DBDE83 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */; };
+ F9C7ED430E8AD93000E953AD /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ED420E8AD93000E953AD /* functioninfo.cc */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -28,11 +26,6 @@
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
- 9BDF186F0B1BB43700F8391B /* dump_syms.h in CopyFiles */,
- 9BE650480B52F6D800611104 /* file_id.h in CopyFiles */,
- 9BE6504A0B52F6D800611104 /* macho_id.h in CopyFiles */,
- 9BE6504C0B52F6D800611104 /* macho_walker.h in CopyFiles */,
- 5578008C0BE1F3AB00EC23E0 /* macho_utilities.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@@ -45,13 +38,22 @@
5578008A0BE1F3AB00EC23E0 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
8DD76FA10486AA7600D96B5E /* dump_syms */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dump_syms; sourceTree = BUILT_PRODUCTS_DIR; };
9BDF186D0B1BB43700F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = "<group>"; };
- 9BDF186E0B1BB43700F8391B /* dump_syms_tool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = dump_syms_tool.m; sourceTree = "<group>"; };
+ 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dump_syms_tool.mm; sourceTree = "<group>"; };
9BE650410B52F6D800611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
9BE650420B52F6D800611104 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; };
9BE650430B52F6D800611104 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; };
9BE650440B52F6D800611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
9BE650450B52F6D800611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
9BE650460B52F6D800611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/mac/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; };
+ F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/mac/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; };
+ F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/mac/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; };
+ F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/mac/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
+ F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/mac/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; };
+ F9C7ED420E8AD93000E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
+ F9F5344D0E7C902C0012363F /* functioninfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = functioninfo.h; path = ../../../common/mac/dwarf/functioninfo.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -69,6 +71,7 @@
08FB7794FE84155DC02AAC07 /* dump_syms */ = {
isa = PBXGroup;
children = (
+ F9F5344B0E7C8FFC0012363F /* DWARF */,
557800890BE1F3AB00EC23E0 /* macho_utilities.cc */,
5578008A0BE1F3AB00EC23E0 /* macho_utilities.h */,
9BE650410B52F6D800611104 /* file_id.cc */,
@@ -79,7 +82,7 @@
9BE650460B52F6D800611104 /* macho_walker.h */,
9BDF186D0B1BB43700F8391B /* dump_syms.h */,
08FB7796FE84155DC02AAC07 /* dump_syms.mm */,
- 9BDF186E0B1BB43700F8391B /* dump_syms_tool.m */,
+ 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */,
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
@@ -102,6 +105,22 @@
name = Products;
sourceTree = "<group>";
};
+ F9F5344B0E7C8FFC0012363F /* DWARF */ = {
+ isa = PBXGroup;
+ children = (
+ F9C7ED420E8AD93000E953AD /* functioninfo.cc */,
+ F9F5344D0E7C902C0012363F /* functioninfo.h */,
+ F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */,
+ F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */,
+ F95B42300E0E22D100DBDE83 /* dwarf2reader.h */,
+ F95B422D0E0E22D100DBDE83 /* bytereader.h */,
+ F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */,
+ F95B422C0E0E22D100DBDE83 /* bytereader.cc */,
+ F95B42310E0E22D100DBDE83 /* line_state_machine.h */,
+ );
+ name = DWARF;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -129,9 +148,11 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* dump_syms */;
projectDirPath = "";
+ projectRoot = "";
targets = (
8DD76F960486AA7600D96B5E /* dump_syms */,
);
@@ -144,11 +165,14 @@
buildActionMask = 2147483647;
files = (
8DD76F9A0486AA7600D96B5E /* dump_syms.mm in Sources */,
- 9BDF18700B1BB43700F8391B /* dump_syms_tool.m in Sources */,
+ F9C7ED430E8AD93000E953AD /* functioninfo.cc in Sources */,
+ 9BDF18700B1BB43700F8391B /* dump_syms_tool.mm in Sources */,
9BE650470B52F6D800611104 /* file_id.cc in Sources */,
9BE650490B52F6D800611104 /* macho_id.cc in Sources */,
9BE6504B0B52F6D800611104 /* macho_walker.cc in Sources */,
5578008B0BE1F3AB00EC23E0 /* macho_utilities.cc in Sources */,
+ F95B42320E0E22D100DBDE83 /* bytereader.cc in Sources */,
+ F95B42330E0E22D100DBDE83 /* dwarf2reader.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -158,7 +182,9 @@
1DEB927508733DD40010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEPLOYMENT_POSTPROCESSING = YES;
+ GCC_CHAR_IS_UNSIGNED_CHAR = YES;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
@@ -186,10 +212,12 @@
ppc,
i386,
);
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_CHAR_IS_UNSIGNED_CHAR = YES;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "";
HEADER_SEARCH_PATHS = (
@@ -199,6 +227,7 @@
INSTALL_PATH = "$(HOME)/bin";
OTHER_LDFLAGS = "-lcrypto";
PRODUCT_NAME = dump_syms;
+ STRIP_STYLE = "non-global";
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
Added: trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.mm
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.mm Sun Oct 19 13:26:38 2008
@@ -0,0 +1,142 @@
+// 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.
+
+// dump_syms_tool.m: Command line tool that uses the DumpSymbols class.
+// TODO(waylonis): accept stdin
+
+#include <unistd.h>
+#include <mach-o/arch.h>
+
+#include "dump_syms.h"
+#include "common/mac/macho_utilities.h"
+
+typedef struct {
+ NSString *srcPath;
+ NSString *arch;
+ NSString *uuidStr;
+ BOOL result;
+} Options;
+
+//=============================================================================
+static void Start(Options *options) {
+ DumpSymbols *dump = [[DumpSymbols alloc]
+ initWithContentsOfFile:options->srcPath];
+
+ if (!dump) {
+ fprintf(stderr, "%s is not a valid Mach-o file\n",
+ [options->srcPath fileSystemRepresentation]);
+ options->result = NO;
+ return;
+ }
+
+ if (![dump setArchitecture:options->arch]) {
+ fprintf(stderr, "Architecture: %s not available in %s\n",
+ [options->arch UTF8String],
+ [options->srcPath fileSystemRepresentation]);
+ options->result = NO;
+ return;
+ }
+
+ options->result = [dump writeSymbolFile:@"-"];
+}
+
+//=============================================================================
+static void Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
+ fprintf(stderr, "Usage: %s [-a ppc|i386|x86] <Mach-o file>\n",
+ argv[0]);
+ fprintf(stderr, "\t-a: Architecture type [default: native]\n");
+ fprintf(stderr, "\t-h: Usage\n");
+ fprintf(stderr, "\t-?: Usage\n");
+}
+
+//=============================================================================
+static void SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ const NXArchInfo *localArchInfo = NXGetLocalArchInfo();
+ signed char ch;
+
+ if (localArchInfo) {
+ if (localArchInfo->cputype & CPU_ARCH_ABI64)
+ options->arch = (localArchInfo->cputype == CPU_TYPE_POWERPC64) ? @"ppc64":
+ @"x86_64";
+ else
+ options->arch = (localArchInfo->cputype == CPU_TYPE_POWERPC) ? @"ppc" :
+ @"x86";
+ }
+
+ while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) {
+ switch (ch) {
+ case 'a':
+ if (strcmp("ppc", optarg) == 0)
+ options->arch = @"ppc";
+ else if (strcmp("x86", optarg) == 0 || strcmp("i386", optarg) == 0)
+ options->arch = @"x86";
+ else if (strcmp("ppc64", optarg) == 0)
+ options->arch = @"ppc64";
+ else if (strcmp("x86_64", optarg) == 0)
+ options->arch = @"x86_64";
+ else {
+ fprintf(stderr, "%s: Invalid architecture: %s\n", argv[0], optarg);
+ Usage(argc, argv);
+ exit(1);
+ }
+ break;
+ case '?':
+ case 'h':
+ Usage(argc, argv);
+ exit(0);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ fprintf(stderr, "Must specify Mach-o file\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->srcPath = [[NSFileManager defaultManager]
+ stringWithFileSystemRepresentation:argv[optind]
+ length:strlen(argv[optind])];
+}
+
+//=============================================================================
+int main (int argc, const char * argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ Options options;
+
+ bzero(&options, sizeof(Options));
+ SetupOptions(argc, argv, &options);
+ Start(&options);
+
+ [pool release];
+
+ return !options.result;
+}
Modified: trunk/google-breakpad/src/tools/mac/symupload/symupload.m
==============================================================================
--- trunk/google-breakpad/src/tools/mac/symupload/symupload.m (original)
+++ trunk/google-breakpad/src/tools/mac/symupload/symupload.m Sun Oct 19 13:26:38 2008
@@ -56,10 +56,25 @@
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSScanner *scanner = [NSScanner scannerWithString:str];
NSString *line;
- NSArray *parts = nil;
+ NSMutableArray *parts = nil;
+ const int MODULE_ID_INDEX = 3;
+
+ if ([scanner scanUpToString:@"\n" intoString:&line]) {
+ parts = [[NSMutableArray alloc] init];
+ NSScanner *moduleInfoScanner = [NSScanner scannerWithString:line];
+ NSString *moduleInfo;
+ // Get everything BEFORE the module name. None of these properties
+ // can have spaces.
+ for (int i = 0; i <= MODULE_ID_INDEX; i++) {
+ [moduleInfoScanner scanUpToString:@" " intoString:&moduleInfo];
+ [parts addObject:moduleInfo];
+ }
- if ([scanner scanUpToString:@"\n" intoString:&line])
- parts = [line componentsSeparatedByString:@" "];
+ // Now get the module name. This can have a space so we scan to
+ // the end of the line.
+ [moduleInfoScanner scanUpToString:@"\n" intoString:&moduleInfo];
+ [parts addObject:moduleInfo];
+ }
[str release];
Added: trunk/google-breakpad/src/tools/solaris/dump_syms/Makefile
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/tools/solaris/dump_syms/Makefile Sun Oct 19 13:26:38 2008
@@ -0,0 +1,61 @@
+# Copyright (c) 2007, 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.
+
+# Author: Alfred Peng
+
+CXX=CC
+CC=cc
+
+CXXFLAGS=-g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -lelf -ldemangle -D_REENTRANT
+
+.PHONY:all clean
+
+BIN=dump_syms
+
+all:$(BIN)
+
+DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o md5.o
+
+dump_syms:$(DUMP_OBJ)
+ $(CXX) $(CXXFLAGS) -o $@ $^
+
+dump_symbols.o:../../../common/solaris/dump_symbols.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+guid_creator.o:../../../common/solaris/guid_creator.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+file_id.o:../../../common/solaris/file_id.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+md5.o:../../../common/md5.c
+ $(CC) $(CXXFLAGS) -c $^
+
+clean:
+ rm -f $(BIN) $(DUMP_OBJ)
Added: trunk/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc
==============================================================================
--- (empty file)
+++ trunk/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc Sun Oct 19 13:26:38 2008
@@ -0,0 +1,54 @@
+// Copyright (c) 2007, 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.
+
+// Author: Alfred Peng
+
+#include <string>
+#include <cstdio>
+
+#include "common/solaris/dump_symbols.h"
+
+using namespace google_breakpad;
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <binary-with-stab-symbol>\n", argv[0]);
+ return 1;
+ }
+
+ const char *binary = argv[1];
+
+ DumpSymbols dumper;
+ if (!dumper.WriteSymbolFile(binary, fileno(stdout))) {
+ fprintf(stderr, "Failed to write symbol file.\n");
+ return 1;
+ }
+
+ return 0;
+}
Modified: trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
==============================================================================
--- trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc (original)
+++ trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc Sun Oct 19 13:26:38 2008
@@ -285,6 +285,12 @@
// This is an authoritiative file-not-found message.
if (fail_not_found_) {
+ fprintf(stderr,
+ "LocateSymbolFile: SymFindFileInPath: LOCATE_NOT_FOUND error "
+ "for %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str());
return LOCATE_NOT_FOUND;
}
Modified: trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
==============================================================================
--- trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj (original)
+++ trunk/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj Sun Oct 19 13:26:38 2008
@@ -1,319 +1,319 @@
-ï<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="ms_symbol_server_converter"
- ProjectGUID="{1463C4CD-23FC-4DE9-BFDE-283338200157}"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- AdditionalDependencies="dbghelp.lib diaguids.lib"
- AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
- />
- <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"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;_CONSOLE;WIN32_LEAN_AND_MEAN"
- RuntimeLibrary="2"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- AdditionalDependencies="dbghelp.lib diaguids.lib"
- AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
- />
- <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"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- AdditionalDependencies="dbghelp.lib diaguids.lib"
- AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
- />
- <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"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;_CONSOLE;WIN32_LEAN_AND_MEAN"
- RuntimeLibrary="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- AdditionalDependencies="dbghelp.lib diaguids.lib"
- AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
- />
- <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="..\..\..\common\windows\guid_string.cc"
- >
- </File>
- <File
- RelativePath=".\ms_symbol_server_converter.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\..\..\common\windows\guid_string.h"
- >
- </File>
- <File
- RelativePath=".\ms_symbol_server_converter.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils-inl.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>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+ï<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="ms_symbol_server_converter"
+ ProjectGUID="{1463C4CD-23FC-4DE9-BFDE-283338200157}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="dbghelp.lib diaguids.lib"
+ AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
+ />
+ <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"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ RuntimeLibrary="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="dbghelp.lib diaguids.lib"
+ AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
+ />
+ <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"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="dbghelp.lib diaguids.lib"
+ AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
+ />
+ <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"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ RuntimeLibrary="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="dbghelp.lib diaguids.lib"
+ AdditionalLibraryDirectories=""$(VSInstallDir)\DIA SDK\lib""
+ />
+ <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="..\..\..\common\windows\guid_string.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\ms_symbol_server_converter.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ms_symbol_server_converter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.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>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Modified: trunk/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
==============================================================================
--- trunk/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj (original)
+++ trunk/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj Sun Oct 19 13:26:38 2008
@@ -1,222 +1,222 @@
-ï<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="dump_syms"
- ProjectGUID="{792E1530-E2C5-4289-992E-317BA30E9D9F}"
- RootNamespace="dumpsyms"
- Keyword="Win32Proj"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib""
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- 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="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib""
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- 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="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\..\..\common\windows\guid_string.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils-inl.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath=".\dump_syms.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\guid_string.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils.cc"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+ï<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="dump_syms"
+ ProjectGUID="{792E1530-E2C5-4289-992E-317BA30E9D9F}"
+ RootNamespace="dumpsyms"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib""
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ 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="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib""
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ 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="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\dump_syms.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Modified: trunk/google-breakpad/src/tools/windows/symupload/symupload.vcproj
==============================================================================
--- trunk/google-breakpad/src/tools/windows/symupload/symupload.vcproj (original)
+++ trunk/google-breakpad/src/tools/windows/symupload/symupload.vcproj Sun Oct 19 13:26:38 2008
@@ -1,231 +1,231 @@
-ï<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="symupload"
- ProjectGUID="{E156ED87-9DE9-47C8-94EC-A5A9CDD65E18}"
- Keyword="Win32Proj"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- 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=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib" wininet.lib version.lib"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- 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="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- CharacterSet="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib" wininet.lib version.lib"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- 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="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\..\..\common\windows\guid_string.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\http_upload.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils-inl.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\..\..\common\windows\guid_string.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\http_upload.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
- >
- </File>
- <File
- RelativePath="..\..\..\common\windows\string_utils.cc"
- >
- </File>
- <File
- RelativePath=".\symupload.cc"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+ï<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="symupload"
+ ProjectGUID="{E156ED87-9DE9-47C8-94EC-A5A9CDD65E18}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ 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=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib" wininet.lib version.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ 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="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(VSInstallDir)\DIA SDK\include";..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""$(VSInstallDir)\DIA SDK\lib\diaguids.lib" wininet.lib version.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ 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="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\symupload.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]