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



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,
-                      &region_base,
-                      &region_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,
+                           &region_base,
+                           &region_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,
-                      &region_base2,
-                      &region_size2,
-                      &nesting_level, 
-                      reinterpret_cast<vm_region_recurse_info_t>(&submap_info),
-                      &info_count);
-      
+      result =
+        mach_vm_region_recurse(target_task,
+                               &region_base2,
+                               &region_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> &parameters,
                           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", &timestruct);
   printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
                                                timestr);
-  printf("  flags                = 0x%llx\n",  header_.flags);
+  printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
   printf("\n");
 
   for (unsigned int stream_index = 0;

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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
-			/>
-			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
-			/>
-			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
-			/>
-			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
-			/>
-			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
+			/>
+			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
+			/>
+			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
+			/>
+			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib&quot;"
+			/>
+			<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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
-				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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
-				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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
+				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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
+				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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; 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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
-				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; 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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; 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="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+				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="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; 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]