bug 368205 - sync up with breakpad svn (again). r=mento
authorted.mielczarek@gmail.com
Tue, 24 Jul 2007 18:05:56 -0700
changeset 3869 be59e0089a72a8c6de191410aa8cd0663b48bec6
parent 3868 629956c5af01701b97c9c6ca69821259bff80c68
child 3870 a9ba97687b706813853f8ed9c0f875b5cdbe5332
push idunknown
push userunknown
push dateunknown
reviewersmento
bugs368205
milestone1.9a7pre
bug 368205 - sync up with breakpad svn (again). r=mento
toolkit/crashreporter/Makefile.in
toolkit/crashreporter/client/Makefile.in
toolkit/crashreporter/client/crashreporter_win.cpp
toolkit/crashreporter/google-breakpad/Makefile.am
toolkit/crashreporter/google-breakpad/Makefile.in
toolkit/crashreporter/google-breakpad/README
toolkit/crashreporter/google-breakpad/aclocal.m4
toolkit/crashreporter/google-breakpad/configure
toolkit/crashreporter/google-breakpad/configure.ac
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_test.cc
toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.cc
toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.h
toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread_test.cc
toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.cc
toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.h
toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj
toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer-inl.h
toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc
toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.h
toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/windows/Makefile.in
toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.sln
toolkit/crashreporter/google-breakpad/src/client/windows/handler/Makefile.in
toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc
toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h
toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.vcproj
toolkit/crashreporter/google-breakpad/src/client/windows/sender/Makefile.in
toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc
toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.h
toolkit/crashreporter/google-breakpad/src/common/convert_UTF.c
toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h
toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h
toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc
toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h
toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc
toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h
toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h
toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m
toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm
toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc
toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h
toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc
toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h
toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc
toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h
toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc
toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h
toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc
toolkit/crashreporter/google-breakpad/src/common/string_conversion.h
toolkit/crashreporter/google-breakpad/src/common/windows/Makefile.in
toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc
toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h
toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc
toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h
toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h
toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc
toolkit/crashreporter/google-breakpad/src/google_breakpad/common/breakpad_types.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/call_stack.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_module.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_modules.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/memory_region.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/system_info.h
toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h
toolkit/crashreporter/google-breakpad/src/processor/address_map.h
toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h
toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc
toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h
toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc
toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc
toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h
toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h
toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h
toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test
toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc
toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h
toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h
toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h
toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/process_state.cc
toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h
toolkit/crashreporter/google-breakpad/src/processor/range_map.h
toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/scoped_ptr.h
toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc
toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h
toolkit/crashreporter/google-breakpad/src/processor/stack_frame_info.h
toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h
toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.dmp
toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.dump.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.stackwalk.machine_readable.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.stackwalk.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/module1.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/module2.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/module3_bad.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/module4_bad.out
toolkit/crashreporter/google-breakpad/src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym
toolkit/crashreporter/google-breakpad/src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym
toolkit/crashreporter/google-breakpad/src/processor/testdata/test_app.cc
toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc
toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/minidump_upload.cc
toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc
toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm
toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h
toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm
toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.m
toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/minidump_upload.m
toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.m
toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h
toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym
toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.vcproj
toolkit/crashreporter/nsExceptionHandler.cpp
--- a/toolkit/crashreporter/Makefile.in
+++ b/toolkit/crashreporter/Makefile.in
@@ -38,17 +38,17 @@ DEPTH		= ../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = airbag
 LIBXUL_LIBRARY = 1
-LIBRARY_NAME = airbagexception_s
+LIBRARY_NAME = exception_handler_s
 
 REQUIRES = \
 	xpcom \
 	string \
 	xulapp \
 	$(NULL)
 
 DIRS = \
--- a/toolkit/crashreporter/client/Makefile.in
+++ b/toolkit/crashreporter/client/Makefile.in
@@ -50,18 +50,18 @@ REQUIRES = sender
 
 #XXX: should move to toolkit/locale
 DIST_FILES = crashreporter.ini
 
 LOCAL_INCLUDES = -I$(srcdir)/../airbag/src
 
 ifeq ($(OS_ARCH),WINNT)
 CPPSRCS = crashreporter_win.cpp
-LIBS += $(DEPTH)/toolkit/airbag/airbag/src/client/windows/sender/$(LIB_PREFIX)crash_report_sender.$(LIB_SUFFIX)
-LIBS += $(DEPTH)/toolkit/airbag/airbag/src/common/windows/$(LIB_PREFIX)airbag_common_s.$(LIB_SUFFIX)
+LIBS += $(DEPTH)/toolkit/airbag/airbag/src/client/windows/sender/$(LIB_PREFIX)crash_report_sender_s.$(LIB_SUFFIX)
+LIBS += $(DEPTH)/toolkit/airbag/airbag/src/common/windows/$(LIB_PREFIX)breakpad_windows_common_s.$(LIB_SUFFIX)
 LOCAL_INCLUDES += -I$(srcdir)
 RCINCLUDE = crashreporter.rc
 DEFINES += -DUNICODE -D_UNICODE
 OS_LIBS += $(call EXPAND_LIBNAME,comctl32 shell32 wininet)
 MOZ_WINCONSOLE = 0
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/crashreporter/client/crashreporter_win.cpp
+++ b/toolkit/crashreporter/client/crashreporter_win.cpp
@@ -294,27 +294,31 @@ bool SendCrashReport(wstring dumpFile,
 }
 
 DWORD WINAPI SendThreadProc(LPVOID param)
 {
   bool finishedOk;
   SENDTHREADDATA* td = (SENDTHREADDATA*)param;
 
   wstring url(sendURL);
+  wstring result;
+
   if (url.empty()) {
     finishedOk = false;
   }
   else {
-    finishedOk = google_airbag::CrashReportSender
+    finishedOk = (google_breakpad::CrashReportSender
       ::SendCrashReport(url,
                         *(td->query_parameters),
-                        td->dumpFile);
+                        td->dumpFile,
+                        &result)
+                  == google_breakpad::RESULT_SUCCEEDED);
   }
   PostMessage(td->hDlg, WM_UPLOADCOMPLETE, finishedOk ? 1 : 0, 0);
-  delete td;
+
   return 0;
 }
 
 //XXX: change this to use Breakpad's string conversion functions
 // when we update to latest SVN
 bool ConvertString(const char* utf8_string, wstring& ucs2_string)
 {
   wchar_t *buffer = NULL;
--- a/toolkit/crashreporter/google-breakpad/Makefile.am
+++ b/toolkit/crashreporter/google-breakpad/Makefile.am
@@ -42,50 +42,56 @@ dist_doc_DATA = \
 	COPYING \
 	ChangeLog \
 	INSTALL \
 	NEWS \
 	README
 
 
 ## Libraries
-lib_LTLIBRARIES = src/libairbag.la
+lib_LTLIBRARIES = src/libbreakpad.la
 
-src_libairbag_la_SOURCES = \
-	src/google_airbag/common/airbag_types.h \
-	src/google_airbag/common/minidump_format.h \
-	src/google_airbag/processor/call_stack.h \
-	src/google_airbag/processor/memory_region.h \
-	src/google_airbag/processor/minidump.h \
-	src/google_airbag/processor/minidump_processor.h \
-	src/google_airbag/processor/process_state.h \
-	src/google_airbag/processor/stack_frame.h \
-	src/google_airbag/processor/stack_frame_cpu.h \
-	src/google_airbag/processor/stackwalker.h \
-	src/google_airbag/processor/symbol_supplier.h \
+src_libbreakpad_la_SOURCES = \
+	src/google_breakpad/common/breakpad_types.h \
+	src/google_breakpad/common/minidump_format.h \
+	src/google_breakpad/processor/basic_source_line_resolver.h \
+	src/google_breakpad/processor/call_stack.h \
+	src/google_breakpad/processor/code_module.h \
+	src/google_breakpad/processor/code_modules.h \
+	src/google_breakpad/processor/memory_region.h \
+	src/google_breakpad/processor/minidump.h \
+	src/google_breakpad/processor/minidump_processor.h \
+	src/google_breakpad/processor/process_state.h \
+	src/google_breakpad/processor/stack_frame.h \
+	src/google_breakpad/processor/stack_frame_cpu.h \
+	src/google_breakpad/processor/stackwalker.h \
+	src/google_breakpad/processor/symbol_supplier.h \
+	src/google_breakpad/processor/system_info.h \
 	src/processor/address_map.h \
 	src/processor/address_map-inl.h \
+	src/processor/basic_code_module.h \
+	src/processor/basic_code_modules.cc \
+	src/processor/basic_code_modules.h \
+	src/processor/basic_source_line_resolver.cc \
 	src/processor/call_stack.cc \
 	src/processor/contained_range_map.h \
 	src/processor/contained_range_map-inl.h \
 	src/processor/linked_ptr.h \
 	src/processor/minidump.cc \
 	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/process_state.cc \
 	src/processor/range_map.h \
 	src/processor/range_map-inl.h \
 	src/processor/scoped_ptr.h \
 	src/processor/simple_symbol_supplier.cc \
 	src/processor/simple_symbol_supplier.h \
-	src/processor/source_line_resolver.cc \
-	src/processor/source_line_resolver.h \
 	src/processor/stack_frame_info.h \
 	src/processor/stackwalker.cc \
 	src/processor/stackwalker_ppc.cc \
 	src/processor/stackwalker_ppc.h \
 	src/processor/stackwalker_x86.cc \
 	src/processor/stackwalker_x86.h
 
 
@@ -93,111 +99,183 @@ src_libairbag_la_SOURCES = \
 bin_PROGRAMS = \
 	src/processor/minidump_dump \
 	src/processor/minidump_stackwalk
 
 
 ## Tests
 check_PROGRAMS = \
 	src/processor/address_map_unittest \
+	src/processor/basic_source_line_resolver_unittest \
 	src/processor/contained_range_map_unittest \
 	src/processor/minidump_processor_unittest \
 	src/processor/pathname_stripper_unittest \
 	src/processor/postfix_evaluator_unittest \
-	src/processor/range_map_unittest \
-	src/processor/source_line_resolver_unittest
+	src/processor/range_map_unittest
 
 if SELFTEST
 check_PROGRAMS += \
 	src/processor/stackwalker_selftest
 endif SELFTEST
 
 check_SCRIPTS = \
 	src/processor/minidump_dump_test \
-	src/processor/minidump_stackwalk_test
+	src/processor/minidump_stackwalk_test \
+	src/processor/minidump_stackwalk_machine_readable_test
 
 TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
 TESTS_ENVIRONMENT =
 
 src_processor_address_map_unittest_SOURCES = \
 	src/processor/address_map_unittest.cc
 
+src_processor_basic_source_line_resolver_unittest_SOURCES = \
+	src/processor/basic_source_line_resolver_unittest.cc
+src_processor_basic_source_line_resolver_unittest_LDADD = \
+	src/processor/basic_source_line_resolver.lo
+
 src_processor_contained_range_map_unittest_SOURCES = \
 	src/processor/contained_range_map_unittest.cc
 
 src_processor_minidump_processor_unittest_SOURCES = \
 	src/processor/minidump_processor_unittest.cc
 src_processor_minidump_processor_unittest_LDADD = \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump_processor.lo \
 	src/processor/minidump.lo \
 	src/processor/process_state.lo \
 	src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
-	src/processor/stackwalker_x86.lo \
-	src/processor/source_line_resolver.lo
+	src/processor/stackwalker_x86.lo
 
 src_processor_pathname_stripper_unittest_SOURCES = \
 	src/processor/pathname_stripper_unittest.cc
 src_processor_pathname_stripper_unittest_LDADD = \
 	src/processor/pathname_stripper.lo
 
 src_processor_postfix_evaluator_unittest_SOURCES = \
 	src/processor/postfix_evaluator_unittest.cc
 
 src_processor_range_map_unittest_SOURCES = \
 	src/processor/range_map_unittest.cc
 
-src_processor_source_line_resolver_unittest_SOURCES = \
-	src/processor/source_line_resolver_unittest.cc
-src_processor_source_line_resolver_unittest_LDADD = \
-	src/processor/source_line_resolver.lo
-
 src_processor_stackwalker_selftest_SOURCES = \
 	src/processor/stackwalker_selftest.cc
 src_processor_stackwalker_selftest_LDADD = \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump.lo \
-	src/processor/source_line_resolver.lo \
 	src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
 	src/processor/stackwalker_x86.lo
 
 ## Non-installables
 noinst_PROGRAMS =
 noinst_SCRIPTS = $(check_SCRIPTS)
 
 src_processor_minidump_dump_SOURCES = \
 	src/processor/minidump_dump.cc
 src_processor_minidump_dump_LDADD = \
+	src/processor/basic_code_modules.lo \
 	src/processor/minidump.lo
 
 src_processor_minidump_stackwalk_SOURCES = \
 	src/processor/minidump_stackwalk.cc
 src_processor_minidump_stackwalk_LDADD = \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump.lo \
 	src/processor/minidump_processor.lo \
 	src/processor/pathname_stripper.lo \
 	src/processor/process_state.lo \
 	src/processor/simple_symbol_supplier.lo \
 	src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
-	src/processor/stackwalker_x86.lo \
-	src/processor/source_line_resolver.lo
+	src/processor/stackwalker_x86.lo
 
 
 ## Additional files to be included in a source distribution
+##
+## find src/client src/common src/processor/testdata src/tools \
+##     -type f \! -path '*/.svn/*' -print | sort
 EXTRA_DIST = \
 	$(SCRIPTS) \
-	src/processor/testdata/minidump1.dmp \
-	src/processor/testdata/minidump1.out \
-	src/processor/testdata/minidump1.stack.out \
+	src/client/mac/handler/exception_handler.cc \
+	src/client/mac/handler/exception_handler.h \
+	src/client/mac/handler/exception_handler_test.cc \
+	src/client/mac/handler/minidump_generator.cc \
+	src/client/mac/handler/minidump_generator.h \
+	src/client/mac/handler/minidump_generator_test.cc \
+	src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
+	src/client/minidump_file_writer.cc \
+	src/client/minidump_file_writer.h \
+	src/client/minidump_file_writer-inl.h \
+	src/client/minidump_file_writer_unittest.cc \
+	src/client/windows/breakpad_client.sln \
+	src/client/windows/handler/exception_handler.cc \
+	src/client/windows/handler/exception_handler.h \
+	src/client/windows/handler/exception_handler.vcproj \
+	src/client/windows/sender/crash_report_sender.cc \
+	src/client/windows/sender/crash_report_sender.h \
+	src/client/windows/sender/crash_report_sender.vcproj \
+	src/common/convert_UTF.c \
+	src/common/convert_UTF.h \
+	src/common/mac/HTTPMultipartUpload.h \
+	src/common/mac/HTTPMultipartUpload.m \
+	src/common/mac/dump_syms.h \
+	src/common/mac/dump_syms.mm \
+	src/common/mac/file_id.cc \
+	src/common/mac/file_id.h \
+	src/common/mac/macho_id.cc \
+	src/common/mac/macho_id.h \
+	src/common/mac/macho_walker.cc \
+	src/common/mac/macho_walker.h \
+	src/common/mac/string_utilities.cc \
+	src/common/mac/string_utilities.h \
+	src/common/string_conversion.cc \
+	src/common/string_conversion.h \
+	src/common/windows/guid_string.cc \
+	src/common/windows/guid_string.h \
+	src/common/windows/http_upload.cc \
+	src/common/windows/http_upload.h \
+	src/common/windows/pdb_source_line_writer.cc \
+	src/common/windows/pdb_source_line_writer.h \
+	src/common/windows/string_utils-inl.h \
+	src/common/windows/string_utils.cc \
 	src/processor/testdata/minidump2.dmp \
-	src/processor/testdata/minidump2.sym \
+	src/processor/testdata/minidump2.dump.out \
+	src/processor/testdata/minidump2.stackwalk.machine_readable.out \
+	src/processor/testdata/minidump2.stackwalk.out \
 	src/processor/testdata/module1.out \
 	src/processor/testdata/module2.out \
-	src/processor/testdata/module3_bad.out
+	src/processor/testdata/module3_bad.out \
+	src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
+	src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
+	src/processor/testdata/test_app.cc \
+	src/tools/mac/crash_report/crash_report.mm \
+	src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
+	src/tools/mac/crash_report/on_demand_symbol_supplier.h \
+	src/tools/mac/crash_report/on_demand_symbol_supplier.mm \
+	src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj \
+	src/tools/mac/dump_syms/dump_syms_tool.m \
+	src/tools/mac/symupload/minidump_upload.m \
+	src/tools/mac/symupload/symupload.m \
+	src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj \
+	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 \
+	src/tools/windows/dump_syms/dump_syms.cc \
+	src/tools/windows/dump_syms/dump_syms.vcproj \
+	src/tools/windows/dump_syms/run_regtest.sh \
+	src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
+	src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
+	src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
+	src/tools/windows/symupload/symupload.cc \
+	src/tools/windows/symupload/symupload.vcproj
 
 
 ## Additional rules
 libtool: $(LIBTOOL_DEPS)
 	$(SHELL) ./config.status --recheck
--- a/toolkit/crashreporter/google-breakpad/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/Makefile.in
@@ -66,23 +66,22 @@ POST_INSTALL = :
 NORMAL_UNINSTALL = :
 PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = src/processor/minidump_dump$(EXEEXT) \
 	src/processor/minidump_stackwalk$(EXEEXT)
 check_PROGRAMS = src/processor/address_map_unittest$(EXEEXT) \
+	src/processor/basic_source_line_resolver_unittest$(EXEEXT) \
 	src/processor/contained_range_map_unittest$(EXEEXT) \
 	src/processor/minidump_processor_unittest$(EXEEXT) \
 	src/processor/pathname_stripper_unittest$(EXEEXT) \
 	src/processor/postfix_evaluator_unittest$(EXEEXT) \
-	src/processor/range_map_unittest$(EXEEXT) \
-	src/processor/source_line_resolver_unittest$(EXEEXT) \
-	$(am__EXEEXT_1)
+	src/processor/range_map_unittest$(EXEEXT) $(am__EXEEXT_1)
 @SELFTEST_TRUE@am__append_1 = \
 @SELFTEST_TRUE@	src/processor/stackwalker_selftest
 
 noinst_PROGRAMS =
 DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \
 	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
 	$(top_srcdir)/configure $(top_srcdir)/src/config.h.in AUTHORS \
 	COPYING ChangeLog INSTALL NEWS autotools/config.guess \
@@ -103,99 +102,103 @@ am__vpath_adj = case $$p in \
     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
     *) f=$$p;; \
   esac;
 am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
 am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
 	"$(DESTDIR)$(docdir)"
 libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
-src_libairbag_la_LIBADD =
+src_libbreakpad_la_LIBADD =
 am__dirstamp = $(am__leading_dot)dirstamp
-am_src_libairbag_la_OBJECTS = src/processor/call_stack.lo \
-	src/processor/minidump.lo src/processor/minidump_processor.lo \
+am_src_libbreakpad_la_OBJECTS = src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
+	src/processor/call_stack.lo src/processor/minidump.lo \
+	src/processor/minidump_processor.lo \
 	src/processor/pathname_stripper.lo \
 	src/processor/process_state.lo \
 	src/processor/simple_symbol_supplier.lo \
-	src/processor/source_line_resolver.lo \
 	src/processor/stackwalker.lo src/processor/stackwalker_ppc.lo \
 	src/processor/stackwalker_x86.lo
-src_libairbag_la_OBJECTS = $(am_src_libairbag_la_OBJECTS)
+src_libbreakpad_la_OBJECTS = $(am_src_libbreakpad_la_OBJECTS)
 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 @SELFTEST_TRUE@am__EXEEXT_1 =  \
 @SELFTEST_TRUE@	src/processor/stackwalker_selftest$(EXEEXT)
 PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
 am_src_processor_address_map_unittest_OBJECTS =  \
 	src/processor/address_map_unittest.$(OBJEXT)
 src_processor_address_map_unittest_OBJECTS =  \
 	$(am_src_processor_address_map_unittest_OBJECTS)
 src_processor_address_map_unittest_LDADD = $(LDADD)
+am_src_processor_basic_source_line_resolver_unittest_OBJECTS =  \
+	src/processor/basic_source_line_resolver_unittest.$(OBJEXT)
+src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_basic_source_line_resolver_unittest_OBJECTS)
+src_processor_basic_source_line_resolver_unittest_DEPENDENCIES =  \
+	src/processor/basic_source_line_resolver.lo
 am_src_processor_contained_range_map_unittest_OBJECTS =  \
 	src/processor/contained_range_map_unittest.$(OBJEXT)
 src_processor_contained_range_map_unittest_OBJECTS =  \
 	$(am_src_processor_contained_range_map_unittest_OBJECTS)
 src_processor_contained_range_map_unittest_LDADD = $(LDADD)
 am_src_processor_minidump_dump_OBJECTS =  \
 	src/processor/minidump_dump.$(OBJEXT)
 src_processor_minidump_dump_OBJECTS =  \
 	$(am_src_processor_minidump_dump_OBJECTS)
-src_processor_minidump_dump_DEPENDENCIES = src/processor/minidump.lo
+src_processor_minidump_dump_DEPENDENCIES =  \
+	src/processor/basic_code_modules.lo src/processor/minidump.lo
 am_src_processor_minidump_processor_unittest_OBJECTS =  \
 	src/processor/minidump_processor_unittest.$(OBJEXT)
 src_processor_minidump_processor_unittest_OBJECTS =  \
 	$(am_src_processor_minidump_processor_unittest_OBJECTS)
 src_processor_minidump_processor_unittest_DEPENDENCIES =  \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump_processor.lo src/processor/minidump.lo \
 	src/processor/process_state.lo src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
-	src/processor/stackwalker_x86.lo \
-	src/processor/source_line_resolver.lo
+	src/processor/stackwalker_x86.lo
 am_src_processor_minidump_stackwalk_OBJECTS =  \
 	src/processor/minidump_stackwalk.$(OBJEXT)
 src_processor_minidump_stackwalk_OBJECTS =  \
 	$(am_src_processor_minidump_stackwalk_OBJECTS)
 src_processor_minidump_stackwalk_DEPENDENCIES =  \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo src/processor/minidump.lo \
 	src/processor/minidump_processor.lo \
 	src/processor/pathname_stripper.lo \
 	src/processor/process_state.lo \
 	src/processor/simple_symbol_supplier.lo \
 	src/processor/stackwalker.lo src/processor/stackwalker_ppc.lo \
-	src/processor/stackwalker_x86.lo \
-	src/processor/source_line_resolver.lo
+	src/processor/stackwalker_x86.lo
 am_src_processor_pathname_stripper_unittest_OBJECTS =  \
 	src/processor/pathname_stripper_unittest.$(OBJEXT)
 src_processor_pathname_stripper_unittest_OBJECTS =  \
 	$(am_src_processor_pathname_stripper_unittest_OBJECTS)
 src_processor_pathname_stripper_unittest_DEPENDENCIES =  \
 	src/processor/pathname_stripper.lo
 am_src_processor_postfix_evaluator_unittest_OBJECTS =  \
 	src/processor/postfix_evaluator_unittest.$(OBJEXT)
 src_processor_postfix_evaluator_unittest_OBJECTS =  \
 	$(am_src_processor_postfix_evaluator_unittest_OBJECTS)
 src_processor_postfix_evaluator_unittest_LDADD = $(LDADD)
 am_src_processor_range_map_unittest_OBJECTS =  \
 	src/processor/range_map_unittest.$(OBJEXT)
 src_processor_range_map_unittest_OBJECTS =  \
 	$(am_src_processor_range_map_unittest_OBJECTS)
 src_processor_range_map_unittest_LDADD = $(LDADD)
-am_src_processor_source_line_resolver_unittest_OBJECTS =  \
-	src/processor/source_line_resolver_unittest.$(OBJEXT)
-src_processor_source_line_resolver_unittest_OBJECTS =  \
-	$(am_src_processor_source_line_resolver_unittest_OBJECTS)
-src_processor_source_line_resolver_unittest_DEPENDENCIES =  \
-	src/processor/source_line_resolver.lo
 am_src_processor_stackwalker_selftest_OBJECTS =  \
 	src/processor/stackwalker_selftest.$(OBJEXT)
 src_processor_stackwalker_selftest_OBJECTS =  \
 	$(am_src_processor_stackwalker_selftest_OBJECTS)
 src_processor_stackwalker_selftest_DEPENDENCIES =  \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo src/processor/minidump.lo \
-	src/processor/source_line_resolver.lo \
 	src/processor/stackwalker.lo src/processor/stackwalker_ppc.lo \
 	src/processor/stackwalker_x86.lo
 SCRIPTS = $(noinst_SCRIPTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src
 depcomp = $(SHELL) $(top_srcdir)/autotools/depcomp
 am__depfiles_maybe = depfiles
 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
 	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -208,37 +211,37 @@ CXXLINK = $(LIBTOOL) --tag=CXX --mode=li
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
 	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
 	$(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(src_libairbag_la_SOURCES) \
+SOURCES = $(src_libbreakpad_la_SOURCES) \
 	$(src_processor_address_map_unittest_SOURCES) \
+	$(src_processor_basic_source_line_resolver_unittest_SOURCES) \
 	$(src_processor_contained_range_map_unittest_SOURCES) \
 	$(src_processor_minidump_dump_SOURCES) \
 	$(src_processor_minidump_processor_unittest_SOURCES) \
 	$(src_processor_minidump_stackwalk_SOURCES) \
 	$(src_processor_pathname_stripper_unittest_SOURCES) \
 	$(src_processor_postfix_evaluator_unittest_SOURCES) \
 	$(src_processor_range_map_unittest_SOURCES) \
-	$(src_processor_source_line_resolver_unittest_SOURCES) \
 	$(src_processor_stackwalker_selftest_SOURCES)
-DIST_SOURCES = $(src_libairbag_la_SOURCES) \
+DIST_SOURCES = $(src_libbreakpad_la_SOURCES) \
 	$(src_processor_address_map_unittest_SOURCES) \
+	$(src_processor_basic_source_line_resolver_unittest_SOURCES) \
 	$(src_processor_contained_range_map_unittest_SOURCES) \
 	$(src_processor_minidump_dump_SOURCES) \
 	$(src_processor_minidump_processor_unittest_SOURCES) \
 	$(src_processor_minidump_stackwalk_SOURCES) \
 	$(src_processor_pathname_stripper_unittest_SOURCES) \
 	$(src_processor_postfix_evaluator_unittest_SOURCES) \
 	$(src_processor_range_map_unittest_SOURCES) \
-	$(src_processor_source_line_resolver_unittest_SOURCES) \
 	$(src_processor_stackwalker_selftest_SOURCES)
 dist_docDATA_INSTALL = $(INSTALL_DATA)
 DATA = $(dist_doc_DATA)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -360,142 +363,217 @@ AM_CPPFLAGS = -I$(top_srcdir)/src
 dist_doc_DATA = \
 	AUTHORS \
 	COPYING \
 	ChangeLog \
 	INSTALL \
 	NEWS \
 	README
 
-lib_LTLIBRARIES = src/libairbag.la
-src_libairbag_la_SOURCES = \
-	src/google_airbag/common/airbag_types.h \
-	src/google_airbag/common/minidump_format.h \
-	src/google_airbag/processor/call_stack.h \
-	src/google_airbag/processor/memory_region.h \
-	src/google_airbag/processor/minidump.h \
-	src/google_airbag/processor/minidump_processor.h \
-	src/google_airbag/processor/process_state.h \
-	src/google_airbag/processor/stack_frame.h \
-	src/google_airbag/processor/stack_frame_cpu.h \
-	src/google_airbag/processor/stackwalker.h \
-	src/google_airbag/processor/symbol_supplier.h \
+lib_LTLIBRARIES = src/libbreakpad.la
+src_libbreakpad_la_SOURCES = \
+	src/google_breakpad/common/breakpad_types.h \
+	src/google_breakpad/common/minidump_format.h \
+	src/google_breakpad/processor/basic_source_line_resolver.h \
+	src/google_breakpad/processor/call_stack.h \
+	src/google_breakpad/processor/code_module.h \
+	src/google_breakpad/processor/code_modules.h \
+	src/google_breakpad/processor/memory_region.h \
+	src/google_breakpad/processor/minidump.h \
+	src/google_breakpad/processor/minidump_processor.h \
+	src/google_breakpad/processor/process_state.h \
+	src/google_breakpad/processor/stack_frame.h \
+	src/google_breakpad/processor/stack_frame_cpu.h \
+	src/google_breakpad/processor/stackwalker.h \
+	src/google_breakpad/processor/symbol_supplier.h \
+	src/google_breakpad/processor/system_info.h \
 	src/processor/address_map.h \
 	src/processor/address_map-inl.h \
+	src/processor/basic_code_module.h \
+	src/processor/basic_code_modules.cc \
+	src/processor/basic_code_modules.h \
+	src/processor/basic_source_line_resolver.cc \
 	src/processor/call_stack.cc \
 	src/processor/contained_range_map.h \
 	src/processor/contained_range_map-inl.h \
 	src/processor/linked_ptr.h \
 	src/processor/minidump.cc \
 	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/process_state.cc \
 	src/processor/range_map.h \
 	src/processor/range_map-inl.h \
 	src/processor/scoped_ptr.h \
 	src/processor/simple_symbol_supplier.cc \
 	src/processor/simple_symbol_supplier.h \
-	src/processor/source_line_resolver.cc \
-	src/processor/source_line_resolver.h \
 	src/processor/stack_frame_info.h \
 	src/processor/stackwalker.cc \
 	src/processor/stackwalker_ppc.cc \
 	src/processor/stackwalker_ppc.h \
 	src/processor/stackwalker_x86.cc \
 	src/processor/stackwalker_x86.h
 
 check_SCRIPTS = \
 	src/processor/minidump_dump_test \
-	src/processor/minidump_stackwalk_test
+	src/processor/minidump_stackwalk_test \
+	src/processor/minidump_stackwalk_machine_readable_test
 
 TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
 TESTS_ENVIRONMENT = 
 src_processor_address_map_unittest_SOURCES = \
 	src/processor/address_map_unittest.cc
 
+src_processor_basic_source_line_resolver_unittest_SOURCES = \
+	src/processor/basic_source_line_resolver_unittest.cc
+
+src_processor_basic_source_line_resolver_unittest_LDADD = \
+	src/processor/basic_source_line_resolver.lo
+
 src_processor_contained_range_map_unittest_SOURCES = \
 	src/processor/contained_range_map_unittest.cc
 
 src_processor_minidump_processor_unittest_SOURCES = \
 	src/processor/minidump_processor_unittest.cc
 
 src_processor_minidump_processor_unittest_LDADD = \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump_processor.lo \
 	src/processor/minidump.lo \
 	src/processor/process_state.lo \
 	src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
-	src/processor/stackwalker_x86.lo \
-	src/processor/source_line_resolver.lo
+	src/processor/stackwalker_x86.lo
 
 src_processor_pathname_stripper_unittest_SOURCES = \
 	src/processor/pathname_stripper_unittest.cc
 
 src_processor_pathname_stripper_unittest_LDADD = \
 	src/processor/pathname_stripper.lo
 
 src_processor_postfix_evaluator_unittest_SOURCES = \
 	src/processor/postfix_evaluator_unittest.cc
 
 src_processor_range_map_unittest_SOURCES = \
 	src/processor/range_map_unittest.cc
 
-src_processor_source_line_resolver_unittest_SOURCES = \
-	src/processor/source_line_resolver_unittest.cc
-
-src_processor_source_line_resolver_unittest_LDADD = \
-	src/processor/source_line_resolver.lo
-
 src_processor_stackwalker_selftest_SOURCES = \
 	src/processor/stackwalker_selftest.cc
 
 src_processor_stackwalker_selftest_LDADD = \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump.lo \
-	src/processor/source_line_resolver.lo \
 	src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
 	src/processor/stackwalker_x86.lo
 
 noinst_SCRIPTS = $(check_SCRIPTS)
 src_processor_minidump_dump_SOURCES = \
 	src/processor/minidump_dump.cc
 
 src_processor_minidump_dump_LDADD = \
+	src/processor/basic_code_modules.lo \
 	src/processor/minidump.lo
 
 src_processor_minidump_stackwalk_SOURCES = \
 	src/processor/minidump_stackwalk.cc
 
 src_processor_minidump_stackwalk_LDADD = \
+	src/processor/basic_code_modules.lo \
+	src/processor/basic_source_line_resolver.lo \
 	src/processor/call_stack.lo \
 	src/processor/minidump.lo \
 	src/processor/minidump_processor.lo \
 	src/processor/pathname_stripper.lo \
 	src/processor/process_state.lo \
 	src/processor/simple_symbol_supplier.lo \
 	src/processor/stackwalker.lo \
 	src/processor/stackwalker_ppc.lo \
-	src/processor/stackwalker_x86.lo \
-	src/processor/source_line_resolver.lo
+	src/processor/stackwalker_x86.lo
 
 EXTRA_DIST = \
 	$(SCRIPTS) \
-	src/processor/testdata/minidump1.dmp \
-	src/processor/testdata/minidump1.out \
-	src/processor/testdata/minidump1.stack.out \
+	src/client/mac/handler/exception_handler.cc \
+	src/client/mac/handler/exception_handler.h \
+	src/client/mac/handler/exception_handler_test.cc \
+	src/client/mac/handler/minidump_generator.cc \
+	src/client/mac/handler/minidump_generator.h \
+	src/client/mac/handler/minidump_generator_test.cc \
+	src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
+	src/client/minidump_file_writer.cc \
+	src/client/minidump_file_writer.h \
+	src/client/minidump_file_writer-inl.h \
+	src/client/minidump_file_writer_unittest.cc \
+	src/client/windows/breakpad_client.sln \
+	src/client/windows/handler/exception_handler.cc \
+	src/client/windows/handler/exception_handler.h \
+	src/client/windows/handler/exception_handler.vcproj \
+	src/client/windows/sender/crash_report_sender.cc \
+	src/client/windows/sender/crash_report_sender.h \
+	src/client/windows/sender/crash_report_sender.vcproj \
+	src/common/convert_UTF.c \
+	src/common/convert_UTF.h \
+	src/common/mac/HTTPMultipartUpload.h \
+	src/common/mac/HTTPMultipartUpload.m \
+	src/common/mac/dump_syms.h \
+	src/common/mac/dump_syms.mm \
+	src/common/mac/file_id.cc \
+	src/common/mac/file_id.h \
+	src/common/mac/macho_id.cc \
+	src/common/mac/macho_id.h \
+	src/common/mac/macho_walker.cc \
+	src/common/mac/macho_walker.h \
+	src/common/mac/string_utilities.cc \
+	src/common/mac/string_utilities.h \
+	src/common/string_conversion.cc \
+	src/common/string_conversion.h \
+	src/common/windows/guid_string.cc \
+	src/common/windows/guid_string.h \
+	src/common/windows/http_upload.cc \
+	src/common/windows/http_upload.h \
+	src/common/windows/pdb_source_line_writer.cc \
+	src/common/windows/pdb_source_line_writer.h \
+	src/common/windows/string_utils-inl.h \
+	src/common/windows/string_utils.cc \
 	src/processor/testdata/minidump2.dmp \
-	src/processor/testdata/minidump2.sym \
+	src/processor/testdata/minidump2.dump.out \
+	src/processor/testdata/minidump2.stackwalk.machine_readable.out \
+	src/processor/testdata/minidump2.stackwalk.out \
 	src/processor/testdata/module1.out \
 	src/processor/testdata/module2.out \
-	src/processor/testdata/module3_bad.out
+	src/processor/testdata/module3_bad.out \
+	src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
+	src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
+	src/processor/testdata/test_app.cc \
+	src/tools/mac/crash_report/crash_report.mm \
+	src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
+	src/tools/mac/crash_report/on_demand_symbol_supplier.h \
+	src/tools/mac/crash_report/on_demand_symbol_supplier.mm \
+	src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj \
+	src/tools/mac/dump_syms/dump_syms_tool.m \
+	src/tools/mac/symupload/minidump_upload.m \
+	src/tools/mac/symupload/symupload.m \
+	src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj \
+	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 \
+	src/tools/windows/dump_syms/dump_syms.cc \
+	src/tools/windows/dump_syms/dump_syms.vcproj \
+	src/tools/windows/dump_syms/run_regtest.sh \
+	src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
+	src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
+	src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
+	src/tools/windows/symupload/symupload.cc \
+	src/tools/windows/symupload/symupload.vcproj
 
 all: all-am
 
 .SUFFIXES:
 .SUFFIXES: .cc .lo .o .obj
 am--refresh:
 	@:
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
@@ -574,42 +652,45 @@ clean-libLTLIBRARIES:
 	  rm -f "$${dir}/so_locations"; \
 	done
 src/processor/$(am__dirstamp):
 	@$(mkdir_p) src/processor
 	@: > src/processor/$(am__dirstamp)
 src/processor/$(DEPDIR)/$(am__dirstamp):
 	@$(mkdir_p) src/processor/$(DEPDIR)
 	@: > src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/basic_code_modules.lo: src/processor/$(am__dirstamp) \
+	src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/basic_source_line_resolver.lo:  \
+	src/processor/$(am__dirstamp) \
+	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/call_stack.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/minidump.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/minidump_processor.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/pathname_stripper.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/process_state.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/simple_symbol_supplier.lo:  \
 	src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
-src/processor/source_line_resolver.lo: src/processor/$(am__dirstamp) \
-	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/stackwalker.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/stackwalker_ppc.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/stackwalker_x86.lo: src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/$(am__dirstamp):
 	@$(mkdir_p) src
 	@: > src/$(am__dirstamp)
-src/libairbag.la: $(src_libairbag_la_OBJECTS) $(src_libairbag_la_DEPENDENCIES) src/$(am__dirstamp)
-	$(CXXLINK) -rpath $(libdir) $(src_libairbag_la_LDFLAGS) $(src_libairbag_la_OBJECTS) $(src_libairbag_la_LIBADD) $(LIBS)
+src/libbreakpad.la: $(src_libbreakpad_la_OBJECTS) $(src_libbreakpad_la_DEPENDENCIES) src/$(am__dirstamp)
+	$(CXXLINK) -rpath $(libdir) $(src_libbreakpad_la_LDFLAGS) $(src_libbreakpad_la_OBJECTS) $(src_libbreakpad_la_LIBADD) $(LIBS)
 install-binPROGRAMS: $(bin_PROGRAMS)
 	@$(NORMAL_INSTALL)
 	test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
 	@list='$(bin_PROGRAMS)'; for p in $$list; do \
 	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
 	  if test -f $$p \
 	     || test -f $$p1 \
 	  ; then \
@@ -648,16 +729,22 @@ clean-noinstPROGRAMS:
 	  rm -f $$p $$f ; \
 	done
 src/processor/address_map_unittest.$(OBJEXT):  \
 	src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/address_map_unittest$(EXEEXT): $(src_processor_address_map_unittest_OBJECTS) $(src_processor_address_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
 	@rm -f src/processor/address_map_unittest$(EXEEXT)
 	$(CXXLINK) $(src_processor_address_map_unittest_LDFLAGS) $(src_processor_address_map_unittest_OBJECTS) $(src_processor_address_map_unittest_LDADD) $(LIBS)
+src/processor/basic_source_line_resolver_unittest.$(OBJEXT):  \
+	src/processor/$(am__dirstamp) \
+	src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/basic_source_line_resolver_unittest$(EXEEXT): $(src_processor_basic_source_line_resolver_unittest_OBJECTS) $(src_processor_basic_source_line_resolver_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+	@rm -f src/processor/basic_source_line_resolver_unittest$(EXEEXT)
+	$(CXXLINK) $(src_processor_basic_source_line_resolver_unittest_LDFLAGS) $(src_processor_basic_source_line_resolver_unittest_OBJECTS) $(src_processor_basic_source_line_resolver_unittest_LDADD) $(LIBS)
 src/processor/contained_range_map_unittest.$(OBJEXT):  \
 	src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/contained_range_map_unittest$(EXEEXT): $(src_processor_contained_range_map_unittest_OBJECTS) $(src_processor_contained_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
 	@rm -f src/processor/contained_range_map_unittest$(EXEEXT)
 	$(CXXLINK) $(src_processor_contained_range_map_unittest_LDFLAGS) $(src_processor_contained_range_map_unittest_OBJECTS) $(src_processor_contained_range_map_unittest_LDADD) $(LIBS)
 src/processor/minidump_dump.$(OBJEXT): src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
@@ -689,32 +776,31 @@ src/processor/postfix_evaluator_unittest
 	@rm -f src/processor/postfix_evaluator_unittest$(EXEEXT)
 	$(CXXLINK) $(src_processor_postfix_evaluator_unittest_LDFLAGS) $(src_processor_postfix_evaluator_unittest_OBJECTS) $(src_processor_postfix_evaluator_unittest_LDADD) $(LIBS)
 src/processor/range_map_unittest.$(OBJEXT):  \
 	src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/range_map_unittest$(EXEEXT): $(src_processor_range_map_unittest_OBJECTS) $(src_processor_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
 	@rm -f src/processor/range_map_unittest$(EXEEXT)
 	$(CXXLINK) $(src_processor_range_map_unittest_LDFLAGS) $(src_processor_range_map_unittest_OBJECTS) $(src_processor_range_map_unittest_LDADD) $(LIBS)
-src/processor/source_line_resolver_unittest.$(OBJEXT):  \
-	src/processor/$(am__dirstamp) \
-	src/processor/$(DEPDIR)/$(am__dirstamp)
-src/processor/source_line_resolver_unittest$(EXEEXT): $(src_processor_source_line_resolver_unittest_OBJECTS) $(src_processor_source_line_resolver_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
-	@rm -f src/processor/source_line_resolver_unittest$(EXEEXT)
-	$(CXXLINK) $(src_processor_source_line_resolver_unittest_LDFLAGS) $(src_processor_source_line_resolver_unittest_OBJECTS) $(src_processor_source_line_resolver_unittest_LDADD) $(LIBS)
 src/processor/stackwalker_selftest.$(OBJEXT):  \
 	src/processor/$(am__dirstamp) \
 	src/processor/$(DEPDIR)/$(am__dirstamp)
 src/processor/stackwalker_selftest$(EXEEXT): $(src_processor_stackwalker_selftest_OBJECTS) $(src_processor_stackwalker_selftest_DEPENDENCIES) src/processor/$(am__dirstamp)
 	@rm -f src/processor/stackwalker_selftest$(EXEEXT)
 	$(CXXLINK) $(src_processor_stackwalker_selftest_LDFLAGS) $(src_processor_stackwalker_selftest_OBJECTS) $(src_processor_stackwalker_selftest_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
 	-rm -f src/processor/address_map_unittest.$(OBJEXT)
+	-rm -f src/processor/basic_code_modules.$(OBJEXT)
+	-rm -f src/processor/basic_code_modules.lo
+	-rm -f src/processor/basic_source_line_resolver.$(OBJEXT)
+	-rm -f src/processor/basic_source_line_resolver.lo
+	-rm -f src/processor/basic_source_line_resolver_unittest.$(OBJEXT)
 	-rm -f src/processor/call_stack.$(OBJEXT)
 	-rm -f src/processor/call_stack.lo
 	-rm -f src/processor/contained_range_map_unittest.$(OBJEXT)
 	-rm -f src/processor/minidump.$(OBJEXT)
 	-rm -f src/processor/minidump.lo
 	-rm -f src/processor/minidump_dump.$(OBJEXT)
 	-rm -f src/processor/minidump_processor.$(OBJEXT)
 	-rm -f src/processor/minidump_processor.lo
@@ -724,46 +810,44 @@ mostlyclean-compile:
 	-rm -f src/processor/pathname_stripper.lo
 	-rm -f src/processor/pathname_stripper_unittest.$(OBJEXT)
 	-rm -f src/processor/postfix_evaluator_unittest.$(OBJEXT)
 	-rm -f src/processor/process_state.$(OBJEXT)
 	-rm -f src/processor/process_state.lo
 	-rm -f src/processor/range_map_unittest.$(OBJEXT)
 	-rm -f src/processor/simple_symbol_supplier.$(OBJEXT)
 	-rm -f src/processor/simple_symbol_supplier.lo
-	-rm -f src/processor/source_line_resolver.$(OBJEXT)
-	-rm -f src/processor/source_line_resolver.lo
-	-rm -f src/processor/source_line_resolver_unittest.$(OBJEXT)
 	-rm -f src/processor/stackwalker.$(OBJEXT)
 	-rm -f src/processor/stackwalker.lo
 	-rm -f src/processor/stackwalker_ppc.$(OBJEXT)
 	-rm -f src/processor/stackwalker_ppc.lo
 	-rm -f src/processor/stackwalker_selftest.$(OBJEXT)
 	-rm -f src/processor/stackwalker_x86.$(OBJEXT)
 	-rm -f src/processor/stackwalker_x86.lo
 
 distclean-compile:
 	-rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/address_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_code_modules.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/call_stack.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/contained_range_map_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_stackwalk.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/postfix_evaluator_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/process_state.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/range_map_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_line_resolver.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_line_resolver_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_ppc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_selftest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_x86.Plo@am__quote@
 
 .cc.o:
 @am__fastdepCXX_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \
 @am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
@@ -936,17 +1020,17 @@ check-TESTS: $(TESTS)
 	  test -z "$$report" || echo "$$report"; \
 	  echo "$$dashes"; \
 	  test "$$failed" -eq 0; \
 	else :; fi
 
 distdir: $(DISTFILES)
 	$(am__remove_distdir)
 	mkdir $(distdir)
-	$(mkdir_p) $(distdir)/autotools $(distdir)/src $(distdir)/src/processor $(distdir)/src/processor/testdata
+	$(mkdir_p) $(distdir)/autotools $(distdir)/src $(distdir)/src/client $(distdir)/src/client/mac/handler $(distdir)/src/client/mac/handler/minidump_test.xcodeproj $(distdir)/src/client/windows $(distdir)/src/client/windows/handler $(distdir)/src/client/windows/sender $(distdir)/src/common $(distdir)/src/common/mac $(distdir)/src/common/windows $(distdir)/src/processor $(distdir)/src/processor/testdata $(distdir)/src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542 $(distdir)/src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1 $(distdir)/src/tools/mac/crash_report $(distdir)/src/tools/mac/crash_report/crash_report.xcodeproj $(distdir)/src/tools/mac/dump_syms $(distdir)/src/tools/mac/dump_syms/dump_syms.xcodeproj $(distdir)/src/tools/mac/symupload $(distdir)/src/tools/mac/symupload/symupload.xcodeproj $(distdir)/src/tools/windows/converter $(distdir)/src/tools/windows/dump_syms $(distdir)/src/tools/windows/dump_syms/testdata $(distdir)/src/tools/windows/symupload
 	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
 	list='$(DISTFILES)'; for file in $$list; do \
 	  case $$file in \
 	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
 	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
 	  esac; \
 	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
--- a/toolkit/crashreporter/google-breakpad/README
+++ b/toolkit/crashreporter/google-breakpad/README
@@ -1,2 +1,2 @@
-Airbag is a set of client and server components which implement a
+Breakpad is a set of client and server components which implement a
 crash-reporting system.
--- a/toolkit/crashreporter/google-breakpad/aclocal.m4
+++ b/toolkit/crashreporter/google-breakpad/aclocal.m4
@@ -7056,16 +7056,33 @@ AC_DEFUN([_AM_SET_OPTIONS],
 [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
 
 # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
 # -------------------------------------------
 # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
 # Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
--- a/toolkit/crashreporter/google-breakpad/configure
+++ b/toolkit/crashreporter/google-breakpad/configure
@@ -1,11 +1,11 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.60 for airbag 0.1.
+# Generated by GNU Autoconf 2.60 for breakpad 0.1.
 #
 # Report bugs to <opensource@google.com>.
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
 ## --------------------- ##
@@ -706,20 +706,20 @@ ac_config_libobj_dir=.
 LIBOBJS=
 cross_compiling=no
 subdirs=
 MFLAGS=
 MAKEFLAGS=
 SHELL=${CONFIG_SHELL-/bin/sh}
 
 # Identity of this package.
-PACKAGE_NAME='airbag'
-PACKAGE_TARNAME='airbag'
+PACKAGE_NAME='breakpad'
+PACKAGE_TARNAME='breakpad'
 PACKAGE_VERSION='0.1'
-PACKAGE_STRING='airbag 0.1'
+PACKAGE_STRING='breakpad 0.1'
 PACKAGE_BUGREPORT='opensource@google.com'
 
 ac_unique_file="README"
 # Factoring default headers for most tests.
 ac_includes_default="\
 #include <stdio.h>
 #if HAVE_SYS_TYPES_H
 # include <sys/types.h>
@@ -1371,17 +1371,17 @@ done
 
 #
 # Report the --help message.
 #
 if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures airbag 0.1 to adapt to many kinds of systems.
+\`configure' configures breakpad 0.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
 To assign environment variables (e.g., CC, CFLAGS...), specify them as
 VAR=VALUE.  See below for descriptions of some of the useful variables.
 
 Defaults for the options are specified in brackets.
 
@@ -1419,17 +1419,17 @@ Fine tuning of the installation director
   --libdir=DIR           object code libraries [EPREFIX/lib]
   --includedir=DIR       C header files [PREFIX/include]
   --oldincludedir=DIR    C header files for non-gcc [/usr/include]
   --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
   --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
   --infodir=DIR          info documentation [DATAROOTDIR/info]
   --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
   --mandir=DIR           man documentation [DATAROOTDIR/man]
-  --docdir=DIR           documentation root [DATAROOTDIR/doc/airbag]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/breakpad]
   --htmldir=DIR          html documentation [DOCDIR]
   --dvidir=DIR           dvi documentation [DOCDIR]
   --pdfdir=DIR           pdf documentation [DOCDIR]
   --psdir=DIR            ps documentation [DOCDIR]
 _ACEOF
 
   cat <<\_ACEOF
 
@@ -1441,17 +1441,17 @@ Program names:
 System types:
   --build=BUILD     configure for building on BUILD [guessed]
   --host=HOST       cross-compile to build programs to run on HOST [BUILD]
 _ACEOF
 fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of airbag 0.1:";;
+     short | recursive ) echo "Configuration of breakpad 0.1:";;
    esac
   cat <<\_ACEOF
 
 Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-dependency-tracking  speeds up one-time build
   --enable-dependency-tracking   do not reject slow dependency extractors
@@ -1544,31 +1544,31 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_
     fi || ac_status=$?
     cd "$ac_pwd" || { ac_status=$?; break; }
   done
 fi
 
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-airbag configure 0.1
+breakpad configure 0.1
 generated by GNU Autoconf 2.60
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
   exit
 fi
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by airbag $as_me 0.1, which was
+It was created by breakpad $as_me 0.1, which was
 generated by GNU Autoconf 2.60.  Invocation command line was
 
   $ $0 $@
 
 _ACEOF
 exec 5>>config.log
 {
 cat <<_ASUNAME
@@ -2229,17 +2229,17 @@ if test -z "$CYGPATH_W"; then
     CYGPATH_W='cygpath -w'
   else
     CYGPATH_W=echo
   fi
 fi
 
 
 # Define the identity of the package.
- PACKAGE='airbag'
+ PACKAGE='breakpad'
  VERSION='0.1'
 
 
 cat >>confdefs.h <<_ACEOF
 #define PACKAGE "$PACKAGE"
 _ACEOF
 
 
@@ -2370,17 +2370,98 @@ fi
 INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
 
 # We need awk for the "check" target.  The system "awk" is bad on
 # some platforms.
 # Always define AMTAR for backward compatibility.
 
 AMTAR=${AMTAR-"${am_missing_run}tar"}
 
-am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+{ echo "$as_me:$LINENO: checking how to create a ustar tar archive" >&5
+echo $ECHO_N "checking how to create a ustar tar archive... $ECHO_C" >&6; }
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar plaintar pax cpio none'
+_am_tools=${am_cv_prog_tar_ustar-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      { echo "$as_me:$LINENO: $_am_tar --version" >&5
+   ($_am_tar --version) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } && break
+    done
+    am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x ustar -w "$$tardir"'
+    am__tar_='pax -L -x ustar -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H ustar -L'
+    am__tar_='find "$tardir" -print | cpio -o -H ustar -L'
+    am__untar='cpio -i -H ustar -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_ustar}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+   (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+   ($am__untar <conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+if test "${am_cv_prog_tar_ustar+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  am_cv_prog_tar_ustar=$_am_tool
+fi
+
+{ echo "$as_me:$LINENO: result: $am_cv_prog_tar_ustar" >&5
+echo "${ECHO_T}$am_cv_prog_tar_ustar" >&6; }
 
 
 
 
 
 ac_config_headers="$ac_config_headers src/config.h"
 
 
@@ -5149,17 +5230,17 @@ ia64-*-hpux*)
       HPUX_IA64_MODE="64"
       ;;
     esac
   fi
   rm -rf conftest*
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5157 "configure"' > conftest.$ac_ext
+  echo '#line 5238 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
    if test "$lt_cv_prog_gnu_ld" = yes; then
     case `/usr/bin/file conftest.$ac_objext` in
     *32-bit*)
@@ -7314,21 +7395,21 @@ else
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7322: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7403: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7326: \$? = $ac_status" >&5
+   echo "$as_me:7407: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_rtti_exceptions=yes
      fi
@@ -7582,21 +7663,21 @@ else
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7590: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7671: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7594: \$? = $ac_status" >&5
+   echo "$as_me:7675: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_prog_compiler_pic_works=yes
      fi
@@ -7686,21 +7767,21 @@ else
    # Insert the option either (1) after the last *FLAGS variable, or
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7694: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7775: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:7698: \$? = $ac_status" >&5
+   echo "$as_me:7779: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o=yes
@@ -10138,17 +10219,17 @@ if test "${lt_cv_dlopen_self+set}" = set
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   	  if test "$cross_compiling" = yes; then :
   lt_cv_dlopen_self=cross
 else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10146 "configure"
+#line 10227 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
 #include <dlfcn.h>
 #endif
 
 #include <stdio.h>
 
@@ -10238,17 +10319,17 @@ if test "${lt_cv_dlopen_self_static+set}
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   	  if test "$cross_compiling" = yes; then :
   lt_cv_dlopen_self_static=cross
 else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10246 "configure"
+#line 10327 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
 #include <dlfcn.h>
 #endif
 
 #include <stdio.h>
 
@@ -12606,21 +12687,21 @@ else
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12614: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12695: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:12618: \$? = $ac_status" >&5
+   echo "$as_me:12699: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_prog_compiler_pic_works_CXX=yes
      fi
@@ -12710,21 +12791,21 @@ else
    # Insert the option either (1) after the last *FLAGS variable, or
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12718: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12799: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:12722: \$? = $ac_status" >&5
+   echo "$as_me:12803: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o_CXX=yes
@@ -14280,21 +14361,21 @@ else
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14288: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14369: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14292: \$? = $ac_status" >&5
+   echo "$as_me:14373: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_prog_compiler_pic_works_F77=yes
      fi
@@ -14384,21 +14465,21 @@ else
    # Insert the option either (1) after the last *FLAGS variable, or
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14392: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14473: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14396: \$? = $ac_status" >&5
+   echo "$as_me:14477: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o_F77=yes
@@ -16614,21 +16695,21 @@ else
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16622: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16703: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16626: \$? = $ac_status" >&5
+   echo "$as_me:16707: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_rtti_exceptions=yes
      fi
@@ -16882,21 +16963,21 @@ else
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16890: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16971: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16894: \$? = $ac_status" >&5
+   echo "$as_me:16975: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_prog_compiler_pic_works_GCJ=yes
      fi
@@ -16986,21 +17067,21 @@ else
    # Insert the option either (1) after the last *FLAGS variable, or
    # (2) before a word containing "conftest.", or (3) at the end.
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16994: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17075: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:16998: \$? = $ac_status" >&5
+   echo "$as_me:17079: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
      $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o_GCJ=yes
@@ -20317,17 +20398,17 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr
 
 
 exec 6>&1
 
 # Save the log message, to keep $[0] and so on meaningful, and to
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by airbag $as_me 0.1, which was
+This file was extended by breakpad $as_me 0.1, which was
 generated by GNU Autoconf 2.60.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
   CONFIG_LINKS    = $CONFIG_LINKS
   CONFIG_COMMANDS = $CONFIG_COMMANDS
   $ $0 $@
 
@@ -20370,17 +20451,17 @@ Configuration headers:
 Configuration commands:
 $config_commands
 
 Report bugs to <bug-autoconf@gnu.org>."
 
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-airbag config.status 0.1
+breakpad config.status 0.1
 configured by $0, generated by GNU Autoconf 2.60,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
 Copyright (C) 2006 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
 ac_pwd='$ac_pwd'
--- a/toolkit/crashreporter/google-breakpad/configure.ac
+++ b/toolkit/crashreporter/google-breakpad/configure.ac
@@ -25,22 +25,22 @@
 # 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.
 
 
 AC_PREREQ(2.57)
 
-AC_INIT(airbag, 0.1, opensource@google.com)
+AC_INIT(breakpad, 0.1, opensource@google.com)
 dnl Sanity check: the argument is just a file that should exist.
 AC_CONFIG_SRCDIR(README)
 AC_CONFIG_AUX_DIR(autotools)
 
-AM_INIT_AUTOMAKE(subdir-objects)
+AM_INIT_AUTOMAKE(subdir-objects tar-ustar)
 AM_CONFIG_HEADER(src/config.h)
 
 AC_PROG_CC
 AC_PROG_CPP
 AC_PROG_CXX
 
 AC_PROG_LIBTOOL
 AC_SUBST(LIBTOOL_DEPS)
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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 <asm/sigcontext.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <ctime>
+
+#include "client/linux/handler/exception_handler.h"
+#include "common/linux/guid_creator.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Signals that we are interested.
+int SigTable[] = {
+#if defined(SIGSEGV)
+  SIGSEGV,
+#endif
+#ifdef SIGABRT
+  SIGABRT,
+#endif
+#ifdef SIGFPE
+  SIGFPE,
+#endif
+#ifdef SIGILL
+  SIGILL,
+#endif
+#ifdef SIGBUS
+  SIGBUS,
+#endif
+};
+
+std::vector<ExceptionHandler*> *ExceptionHandler::handler_stack_ = NULL;
+int ExceptionHandler::handler_stack_index_ = 0;
+pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
+PTHREAD_MUTEX_INITIALIZER;
+
+ExceptionHandler::ExceptionHandler(const string &dump_path,
+                                   FilterCallback filter,
+                                   MinidumpCallback callback,
+                                   void *callback_context,
+                                   bool install_handler)
+    : filter_(filter),
+      callback_(callback),
+      callback_context_(callback_context),
+      dump_path_(),
+      installed_handler_(install_handler) {
+  set_dump_path(dump_path);
+
+  if (install_handler) {
+    SetupHandler();
+    pthread_mutex_lock(&handler_stack_mutex_);
+    if (handler_stack_ == NULL)
+      handler_stack_ = new std::vector<ExceptionHandler *>;
+    handler_stack_->push_back(this);
+    pthread_mutex_unlock(&handler_stack_mutex_);
+  }
+}
+
+ExceptionHandler::~ExceptionHandler() {
+  TeardownAllHandler();
+  pthread_mutex_lock(&handler_stack_mutex_);
+  if (handler_stack_->back() == this) {
+    handler_stack_->pop_back();
+  } else {
+    fprintf(stderr, "warning: removing Breakpad handler out of order\n");
+    for (std::vector<ExceptionHandler *>::iterator iterator =
+         handler_stack_->begin();
+         iterator != handler_stack_->end();
+         ++iterator) {
+      if (*iterator == this) {
+        handler_stack_->erase(iterator);
+      }
+    }
+  }
+
+  if (handler_stack_->empty()) {
+    // When destroying the last ExceptionHandler that installed a handler,
+    // clean up the handler stack.
+    delete handler_stack_;
+    handler_stack_ = NULL;
+  }
+  pthread_mutex_unlock(&handler_stack_mutex_);
+}
+
+bool ExceptionHandler::WriteMinidump() {
+  return InternalWriteMinidump(0, NULL);
+}
+
+// static
+bool ExceptionHandler::WriteMinidump(const string &dump_path,
+                   MinidumpCallback callback,
+                   void *callback_context) {
+  ExceptionHandler handler(dump_path, NULL, callback,
+                           callback_context, false);
+  return handler.InternalWriteMinidump(0, NULL);
+}
+
+void ExceptionHandler::SetupHandler() {
+  // Signal on a different stack to avoid using the stack
+  // of the crashing thread.
+  struct sigaltstack sig_stack;
+  sig_stack.ss_sp = malloc(MINSIGSTKSZ);
+  if (sig_stack.ss_sp == NULL)
+    return;
+  sig_stack.ss_size = MINSIGSTKSZ;
+  sig_stack.ss_flags = 0;
+
+  if (sigaltstack(&sig_stack, NULL) < 0)
+    return;
+  for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i)
+    SetupHandler(SigTable[i]);
+}
+
+void ExceptionHandler::SetupHandler(int signo) {
+  struct sigaction act, old_act;
+  act.sa_handler = HandleException;
+  act.sa_flags = SA_ONSTACK;
+  if (sigaction(signo, &act, &old_act) < 0)
+    return;
+  old_handlers_[signo] = old_act.sa_handler;
+}
+
+void ExceptionHandler::TeardownHandler(int signo) {
+  if (old_handlers_.find(signo) != old_handlers_.end()) {
+    struct sigaction act;
+    act.sa_handler = old_handlers_[signo];
+    act.sa_flags = 0;
+    sigaction(signo, &act, 0);
+  }
+}
+
+void ExceptionHandler::TeardownAllHandler() {
+  for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) {
+    TeardownHandler(SigTable[i]);
+  }
+}
+
+// static
+void ExceptionHandler::HandleException(int signo) {
+  // In Linux, 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. It is the second parameter above the signal number.
+  const struct sigcontext *sig_ctx =
+    reinterpret_cast<const struct sigcontext *>(&signo + 1);
+  pthread_mutex_lock(&handler_stack_mutex_);
+  ExceptionHandler *current_handler =
+    handler_stack_->at(handler_stack_->size() - ++handler_stack_index_);
+  pthread_mutex_unlock(&handler_stack_mutex_);
+
+  // Restore original handler.
+  current_handler->TeardownHandler(signo);
+  if (current_handler->InternalWriteMinidump(signo, sig_ctx)) {
+    // Fully handled this exception, safe to exit.
+    exit(EXIT_FAILURE);
+  } else {
+    // Exception not fully handled, will call the next handler in stack to
+    // process it.
+    typedef void (*SignalHandler)(int signo, struct sigcontext);
+    SignalHandler old_handler =
+      reinterpret_cast<SignalHandler>(current_handler->old_handlers_[signo]);
+    if (old_handler != NULL)
+      old_handler(signo, *sig_ctx);
+  }
+
+  pthread_mutex_lock(&handler_stack_mutex_);
+  current_handler->SetupHandler(signo);
+  --handler_stack_index_;
+  // All the handlers in stack have been invoked to handle the exception,
+  // normally the process should be terminated and should not reach here.
+  // In case we got here, ask the OS to handle it to avoid endless loop,
+  // normally the OS will generate a core and termiate the process. This
+  // may be desired to debug the program.
+  if (handler_stack_index_ == 0)
+    signal(signo, SIG_DFL);
+  pthread_mutex_unlock(&handler_stack_mutex_);
+}
+
+bool ExceptionHandler::InternalWriteMinidump(int signo,
+                                    const struct sigcontext *sig_ctx) {
+  if (filter_ && !filter_(callback_context_))
+    return false;
+
+  GUID guid;
+  bool success = false;;
+  char guid_str[kGUIDStringLength + 1];
+  if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_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, 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);
+  }
+  return success;
+}
+
+}  // namespace google_breakpad
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
@@ -0,0 +1,194 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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_LINUX_HANDLER_EXCEPTION_HANDLER_H__
+#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__
+
+#include <pthread.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "client/linux/handler/minidump_generator.h"
+
+// Context information when exception occured.
+struct sigcontex;
+
+namespace google_breakpad {
+
+using std::string;
+
+//
+// ExceptionHandler
+//
+// ExceptionHandler can write a minidump file when an exception occurs,
+// or when WriteMinidump() is called explicitly by your program.
+//
+// To have the exception handler write minidumps when an uncaught exception
+// (crash) occurs, you should create an instance early in the execution
+// of your program, and keep it around for the entire time you want to
+// have crash handling active (typically, until shutdown).
+// (NOTE): There should be only be one this kind of exception handler
+// object per process.
+//
+// If you want to write minidumps without installing the exception handler,
+// you can create an ExceptionHandler with install_handler set to false,
+// then call WriteMinidump.  You can also use this technique if you want to
+// use different minidump callbacks for different call sites.
+//
+// In either case, a callback function is called when a minidump is written,
+// which receives the unqiue id of the minidump.  The caller can use this
+// id to collect and write additional application state, and to launch an
+// external crash-reporting application.
+//
+// Caller should try to make the callbacks as crash-friendly as possible,
+// it should avoid use heap memory allocation as much as possible.
+//
+class ExceptionHandler {
+ public:
+  // A callback function to run before Breakpad performs any substantial
+  // processing of an exception.  A FilterCallback is called before writing
+  // a minidump.  context is the parameter supplied by the user as
+  // callback_context when the handler was created.
+  //
+  // If a FilterCallback returns true, Breakpad will continue processing,
+  // 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);
+
+  // A callback function to run after the minidump has been written.
+  // minidump_id is a unique id for the dump, so the minidump
+  // file is <dump_path>\<minidump_id>.dmp.  context is the parameter supplied
+  // by the user as callback_context when the handler was created.  succeeded
+  // indicates whether a minidump file was successfully written.
+  //
+  // If an exception occurred and the callback returns true, Breakpad will
+  // treat the exception as fully-handled, suppressing any other handlers from
+  // being notified of the exception.  If the callback returns false, Breakpad
+  // will treat the exception as unhandled, and allow another handler to handle
+  // it. If there are no other handlers, Breakpad will report the exception to
+  // the system as unhandled, allowing a debugger or native crash dialog the
+  // opportunity to handle the exception.  Most callback implementations
+  // 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 char *dump_path,
+                                   const char *minidump_id,
+                                   void *context,
+                                   bool succeeded);
+
+  // Creates a new ExceptionHandler instance to handle writing minidumps.
+  // Before writing a minidump, the optional filter callback will be called.
+  // Its return value determines whether or not Breakpad should write a
+  // minidump.  Minidump files will be written to dump_path, and the optional
+  // callback is called after writing the dump file, as described above.
+  // If install_handler is true, then a minidump will be written whenever
+  // an unhandled exception occurs.  If it is false, minidumps will only
+  // be written when WriteMinidump is called.
+  ExceptionHandler(const string &dump_path,
+                   FilterCallback filter, MinidumpCallback callback,
+                   void *callback_context,
+                   bool install_handler);
+  ~ExceptionHandler();
+
+  // Get and set the minidump path.
+  string dump_path() const { return dump_path_; }
+  void set_dump_path(const string &dump_path) {
+    dump_path_ = dump_path;
+    dump_path_c_ = dump_path_.c_str();
+  }
+
+  // Writes a minidump immediately.  This can be used to capture the
+  // execution state independently of a crash.  Returns true on success.
+  bool WriteMinidump();
+
+    // Convenience form of WriteMinidump which does not require an
+  // ExceptionHandler instance.
+  static bool WriteMinidump(const string &dump_path,
+                            MinidumpCallback callback,
+                            void *callback_context);
+
+ private:
+  // Setup crash handler.
+  void SetupHandler();
+  // Setup signal handler for a signal.
+  void SetupHandler(int signo);
+  // Teardown the handler for a signal.
+  void TeardownHandler(int signo);
+  // Teardown all handlers.
+  void TeardownAllHandler();
+
+  // Signal handler.
+  static void HandleException(int signo);
+
+  bool InternalWriteMinidump(int signo, const struct sigcontext *sig_ctx);
+
+ private:
+  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_;
+
+  // True if the ExceptionHandler installed an unhandled exception filter
+  // when created (with an install_handler parameter set to true).
+  bool installed_handler_;
+
+  // Keep the previous handlers for the signal.
+  typedef void (*sighandler_t)(int);
+  std::map<int, sighandler_t> old_handlers_;
+
+  // The global exception handler stack. This is need becuase there may exist
+  // multiple ExceptionHandler instances in a process. Each will have itself
+  // registered in this stack.
+  static std::vector<ExceptionHandler *> *handler_stack_;
+  // The index of the handler that should handle the next exception.
+  static int handler_stack_index_;
+  static pthread_mutex_t handler_stack_mutex_;
+
+  // The minidump generator.
+  MinidumpGenerator minidump_generator_;
+
+  // disallow copy ctor and operator=
+  explicit ExceptionHandler(const ExceptionHandler &);
+  void operator=(const ExceptionHandler &);
+};
+
+}  // namespace google_breakpad
+
+#endif  // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_test.cc
@@ -0,0 +1,124 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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 <pthread.h>
+#include <unistd.h>
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "client/linux/handler/exception_handler.h"
+#include "client/linux/handler/linux_thread.h"
+
+using namespace google_breakpad;
+
+// Thread use this to see if it should stop working.
+static bool should_exit = false;
+
+static int foo2(int arg) {
+  // Stack variable, used for debugging stack dumps.
+  /*DDDebug*/printf("%s:%d\n", __FUNCTION__, __LINE__);
+  int c = 0xcccccccc;
+  fprintf(stderr, "Thread trying to crash: %x\n", getpid());
+  c = *reinterpret_cast<int *>(0x5);
+  return c;
+}
+
+static int foo(int arg) {
+  // Stack variable, used for debugging stack dumps.
+  int b = 0xbbbbbbbb;
+  b = foo2(b);
+  return b;
+}
+
+static void *thread_crash(void *) {
+  // Stack variable, used for debugging stack dumps.
+  int a = 0xaaaaaaaa;
+  sleep(1);
+  a = foo(a);
+  printf("%x\n", a);
+  return NULL;
+}
+
+static void *thread_main(void *) {
+  while (!should_exit)
+    sleep(1);
+  return NULL;
+}
+
+static void CreateCrashThread() {
+  pthread_t h;
+  pthread_create(&h, NULL, thread_crash, NULL);
+  pthread_detach(h);
+}
+
+// Create working threads.
+static void CreateThread(int num) {
+  pthread_t h;
+  for (int i = 0; i < num; ++i) {
+    pthread_create(&h, NULL, thread_main, NULL);
+    pthread_detach(h);
+  }
+}
+
+// Callback when minidump written.
+static bool MinidumpCallback(const char *dump_path,
+                             const char *minidump_id,
+                             void *context,
+                             bool succeeded) {
+  int index = reinterpret_cast<int>(context);
+  printf("%d %s: %s is dumped\n", index, __FUNCTION__, minidump_id);
+  if (index == 0) {
+    should_exit = true;
+    return true;
+  }
+  // Don't process it.
+  return false;
+}
+
+int main(int argc, char *argv[]) {
+  int handler_index = 0;
+  ExceptionHandler handler_ignore(".", NULL, MinidumpCallback,
+                           (void*)handler_index, true);
+  ++handler_index;
+  ExceptionHandler handler_process(".", NULL, MinidumpCallback,
+                           (void*)handler_index, true);
+  CreateCrashThread();
+  CreateThread(10);
+
+  while (true)
+    sleep(1);
+  should_exit = true;
+
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.cc
@@ -0,0 +1,384 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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 <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/ptrace.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <functional>
+
+#include "client/linux/handler/linux_thread.h"
+
+using namespace google_breakpad;
+
+// This unamed namespace contains helper function.
+namespace {
+
+// 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.
+bool LocalAtoi(char *s, int *r) {
+  assert(s != NULL);
+  assert(r != NULL);
+  char *endptr = NULL;
+  int ret = strtol(s, &endptr, 10);
+  if (endptr == s)
+    return false;
+  *r = ret;
+  return true;
+}
+
+// Fill the proc path of a thread given its id.
+void FillProcPath(int pid, char *path, int path_size) {
+  char pid_str[32];
+  snprintf(pid_str, sizeof(pid_str), "%d", pid);
+  snprintf(path, path_size, "/proc/%s/", pid_str);
+}
+
+// Read thread info from /proc/$pid/status.
+bool ReadThreadInfo(int pid, ThreadInfo *info) {
+  assert(info != NULL);
+  char status_path[80];
+  // Max size we want to read from status file.
+  static const int kStatusMaxSize = 1024;
+  char status_content[kStatusMaxSize];
+
+  FillProcPath(pid, status_path, sizeof(status_path));
+  strcat(status_path, "status");
+  int fd = open(status_path, O_RDONLY, 0);
+  if (fd < 0)
+    return false;
+
+  int num_read = read(fd, status_content, kStatusMaxSize - 1);
+  if (num_read < 0) {
+    close(fd);
+    return false;
+  }
+  close(fd);
+  status_content[num_read] = '\0';
+
+  char *tgid_start = strstr(status_content, "Tgid:");
+  if (tgid_start)
+    sscanf(tgid_start, "Tgid:\t%d\n", &(info->tgid));
+  else
+    // tgid not supported by kernel??
+    info->tgid = 0;
+
+  tgid_start = strstr(status_content, "Pid:");
+  if (tgid_start) {
+    sscanf(tgid_start, "Pid:\t%d\n" "PPid:\t%d\n", &(info->pid),
+           &(info->ppid));
+    return true;
+  }
+  return false;
+}
+
+// Callback invoked for each mapped module.
+// It use the module's adderss range to validate the address.
+bool IsAddressInModuleCallback(const ModuleInfo &module_info,
+                               void *context) {
+  AddressValidatingContext *addr =
+    reinterpret_cast<AddressValidatingContext *>(context);
+  addr->is_mapped = ((addr->address >= module_info.start_addr) &&
+                     (addr->address <= module_info.start_addr +
+                      module_info.size));
+  return !addr->is_mapped;
+}
+
+#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;
+}
+#else
+void *GetNextFrame(void **last_ebp) {
+  return reinterpret_cast<void*>(last_ebp);
+}
+#endif
+
+// Suspend a thread by attaching to it.
+bool SuspendThread(int pid, void *context) {
+  // This may fail if the thread has just died or debugged.
+  errno = 0;
+  if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 &&
+      errno != 0) {
+    return false;
+  }
+  while (waitpid(pid, NULL, __WALL) < 0) {
+    if (errno != EINTR) {
+      ptrace(PTRACE_DETACH, pid, NULL, NULL);
+      return false;
+    }
+  }
+  return true;
+}
+
+// Resume a thread by detaching from it.
+bool ResumeThread(int pid, void *context) {
+  return ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0;
+}
+
+// Callback to get the thread information.
+// Will be called for each thread found.
+bool ThreadInfoCallback(int pid, void *context) {
+  CallbackParam<ThreadCallback> *thread_callback =
+    reinterpret_cast<CallbackParam<ThreadCallback> *>(context);
+  ThreadInfo thread_info;
+  if (ReadThreadInfo(pid, &thread_info) && thread_callback) {
+    // Invoke callback from caller.
+    return (thread_callback->call_back)(thread_info, thread_callback->context);
+  }
+  return false;
+}
+
+}  // namespace
+
+namespace google_breakpad {
+
+LinuxThread::LinuxThread(int pid) : pid_(pid) , threads_suspened_(false) {
+}
+
+LinuxThread::~LinuxThread() {
+  if (threads_suspened_)
+    ResumeAllThreads();
+}
+
+int LinuxThread::SuspendAllThreads() {
+  CallbackParam<PidCallback> callback_param(SuspendThread, NULL);
+  int thread_count = 0;
+  if ((thread_count = IterateProcSelfTask(pid_, &callback_param)) > 0)
+    threads_suspened_ = true;
+  return thread_count;
+}
+
+void LinuxThread::ResumeAllThreads() const {
+  CallbackParam<PidCallback> callback_param(ResumeThread, NULL);
+  IterateProcSelfTask(pid_, &callback_param);
+}
+
+int LinuxThread::GetThreadCount() const {
+  return IterateProcSelfTask(pid_, NULL);
+}
+
+int LinuxThread::ListThreads(
+    CallbackParam<ThreadCallback> *thread_callback_param) const {
+  CallbackParam<PidCallback> callback_param(ThreadInfoCallback,
+                                            thread_callback_param);
+  return IterateProcSelfTask(pid_, &callback_param);
+}
+
+bool LinuxThread::GetRegisters(int pid, user_regs_struct *regs) const {
+  assert(regs);
+  return (regs != NULL &&
+          (ptrace(PTRACE_GETREGS, pid, NULL, regs) == 0) &&
+          errno == 0);
+}
+
+// Get the floating-point registers of a thread.
+// The caller must get the thread pid by ListThreads.
+bool LinuxThread::GetFPRegisters(int pid, user_fpregs_struct *regs) const {
+  assert(regs);
+  return (regs != NULL &&
+          (ptrace(PTRACE_GETREGS, pid, NULL, regs) ==0) &&
+          errno == 0);
+}
+
+bool LinuxThread::GetFPXRegisters(int pid, user_fpxregs_struct *regs) const {
+  assert(regs);
+  return (regs != NULL &&
+          (ptrace(PTRACE_GETFPREGS, pid, NULL, regs) != 0) &&
+          errno == 0);
+}
+
+bool LinuxThread::GetDebugRegisters(int pid, DebugRegs *regs) const {
+  assert(regs);
+
+#define GET_DR(name, num)\
+  name->dr##num = ptrace(PTRACE_PEEKUSER, pid,\
+                         offsetof(struct user, u_debugreg[num]), NULL)
+  GET_DR(regs, 0);
+  GET_DR(regs, 1);
+  GET_DR(regs, 2);
+  GET_DR(regs, 3);
+  GET_DR(regs, 4);
+  GET_DR(regs, 5);
+  GET_DR(regs, 6);
+  GET_DR(regs, 7);
+  return true;
+}
+
+int LinuxThread::GetThreadStackDump(uintptr_t current_ebp,
+                                    uintptr_t current_esp,
+                                    void *buf,
+                                    int buf_size) const {
+  assert(buf);
+  assert(buf_size > 0);
+
+  uintptr_t stack_bottom = GetThreadStackBottom(current_ebp);
+  int size = stack_bottom - current_esp;
+  size = buf_size > size ? size : buf_size;
+  if (size > 0)
+    memcpy(buf, reinterpret_cast<void*>(current_esp), size);
+  return size;
+}
+
+// Get the stack bottom of a thread by stack walking. It works
+// unless the stack has been corrupted or the frame pointer has been omited.
+// This is just a temporary solution before we get better ideas about how
+// this can be done.
+//
+// We will check each frame address by checking into module maps.
+// TODO(liuli): Improve it.
+uintptr_t LinuxThread::GetThreadStackBottom(uintptr_t current_ebp) const {
+  void **sp = reinterpret_cast<void **>(current_ebp);
+  void **previous_sp = sp;
+  while (sp && IsAddressMapped((uintptr_t)sp)) {
+    previous_sp = sp;
+    sp = reinterpret_cast<void **>(GetNextFrame(sp));
+  }
+  return (uintptr_t)previous_sp;
+}
+
+int LinuxThread::GetModuleCount() const {
+  return ListModules(NULL);
+}
+
+int LinuxThread::ListModules(
+    CallbackParam<ModuleCallback> *callback_param) const {
+  char line[512];
+  const char *maps_path = "/proc/self/maps";
+
+  int module_count = 0;
+  FILE *fp = fopen(maps_path, "r");
+  if (fp == NULL)
+    return -1;
+
+  uintptr_t start_addr;
+  uintptr_t end_addr;
+  while (fgets(line, sizeof(line), fp) != NULL) {
+    if (sscanf(line, "%x-%x", &start_addr, &end_addr) == 2) {
+      ModuleInfo module;
+      memset(&module, 0, sizeof(module));
+      module.start_addr = start_addr;
+      module.size = end_addr - start_addr;
+      char *name = NULL;
+      assert(module.size > 0);
+      // Only copy name if the name is a valid path name.
+      if ((name = strchr(line, '/')) != NULL) {
+        // Get rid of the last '\n' in line
+        char *last_return = strchr(line, '\n');
+        if (last_return != NULL)
+          *last_return = '\0';
+        // Keep a space for the ending 0.
+        strncpy(module.name, name, sizeof(module.name) - 1);
+        ++module_count;
+      }
+      if (callback_param &&
+          !(callback_param->call_back(module, callback_param->context)))
+        break;
+    }
+  }
+  fclose(fp);
+  return module_count;
+}
+
+// Parse /proc/$pid/tasks to list all the threads of the process identified by
+// pid.
+int LinuxThread::IterateProcSelfTask(int pid,
+                          CallbackParam<PidCallback> *callback_param) const {
+  char task_path[80];
+  FillProcPath(pid, task_path, sizeof(task_path));
+  strcat(task_path, "task");
+
+  DIR *dir = opendir(task_path);
+  if (dir == NULL)
+    return -1;
+
+  int pid_number = 0;
+  // Record the last pid we've found. This is used for duplicated thread
+  // removal. Duplicated thread information can be found in /proc/$pid/tasks.
+  int last_pid = -1;
+  struct dirent *entry = NULL;
+  while ((entry = readdir(dir)) != NULL) {
+    if (strcmp(entry->d_name, ".") &&
+        strcmp(entry->d_name, "..")) {
+      int tpid = 0;
+      if (LocalAtoi(entry->d_name, &tpid) &&
+          last_pid != tpid) {
+        last_pid = tpid;
+        ++pid_number;
+        // Invoke the callback.
+        if (callback_param &&
+            !(callback_param->call_back)(tpid, callback_param->context))
+          break;
+      }
+    }
+  }
+  closedir(dir);
+  return pid_number;
+}
+
+// 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 LinuxThread::IsAddressMapped(uintptr_t address) const {
+  AddressValidatingContext addr;
+  addr.address = address;
+  CallbackParam<ModuleCallback> callback_param(IsAddressInModuleCallback,
+                                               &addr);
+  ListModules(&callback_param);
+  return addr.is_mapped;
+}
+
+}  // namespace google_breakpad
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.h
@@ -0,0 +1,201 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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_LINUX_HANDLER_LINUX_THREAD_H__
+#define CLIENT_LINUX_HANDLER_LINUX_THREAD_H__
+
+#include <stdint.h>
+#include <sys/user.h>
+
+namespace google_breakpad {
+
+// Max module path name length.
+#define kMaxModuleNameLength 256
+
+// Holding information about a thread in the process.
+struct ThreadInfo {
+  // Id of the thread group.
+  int tgid;
+  // Id of the thread.
+  int pid;
+  // Id of the parent process.
+  int ppid;
+};
+
+// Holding infomaton about a module in the process.
+struct ModuleInfo {
+  char name[kMaxModuleNameLength];
+  uintptr_t start_addr;
+  int size;
+};
+
+// Holding debug registers.
+struct DebugRegs {
+  int dr0;
+  int dr1;
+  int dr2;
+  int dr3;
+  int dr4;
+  int dr5;
+  int dr6;
+  int dr7;
+};
+
+// A callback to run when got a thread in the process.
+// Return true will go on to the next thread while return false will stop the
+// iteration.
+typedef bool (*ThreadCallback)(const ThreadInfo &thread_info, void *context);
+
+// A callback to run when a new module is found in the process.
+// Return true will go on to the next module while return false will stop the
+// iteration.
+typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context);
+
+// Holding the callback information.
+template<class CallbackFunc>
+struct CallbackParam {
+  // Callback function address.
+  CallbackFunc call_back;
+  // Callback context;
+  void *context;
+
+  CallbackParam() : call_back(NULL), context(NULL) {
+  }
+
+  CallbackParam(CallbackFunc func, void *func_context) :
+    call_back(func), context(func_context) {
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// LinuxThread
+//
+// Provides handy support for operation on linux threads.
+// It uses ptrace to get thread registers. Since ptrace only works in a
+// different process other than the one being ptraced, user of this class
+// should create another process before using the class.
+//
+// The process should be created in the following way:
+//    int cloned_pid = clone(ProcessEntryFunction, stack_address,
+//                           CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
+//                           (void*)&arguments);
+//    waitpid(cloned_pid, NULL, __WALL);
+//
+// If CLONE_VM is not used, GetThreadStackBottom, GetThreadStackDump
+// will not work since it just use memcpy to get the stack dump.
+//
+class LinuxThread {
+ public:
+  // Create a LinuxThread instance to list all the threads in a process.
+  explicit LinuxThread(int pid);
+  ~LinuxThread();
+
+  // Stop all the threads in the process.
+  // Return the number of stopped threads in the process.
+  // Return -1 means failed to stop threads.
+  int SuspendAllThreads();
+
+  // Resume all the suspended threads.
+  void ResumeAllThreads() const;
+
+  // Get the count of threads in the process.
+  // Return -1 means error.
+  int GetThreadCount() const;
+
+  // List the threads of process.
+  // Whenever there is a thread found, the callback will be invoked to process
+  // the information.
+  // Return number of threads listed.
+  int ListThreads(CallbackParam<ThreadCallback> *thread_callback_param) const;
+
+  // Get the general purpose registers of a thread.
+  // The caller must get the thread pid by ListThreads.
+  bool GetRegisters(int pid, user_regs_struct *regs) const;
+
+  // Get the floating-point registers of a thread.
+  // The caller must get the thread pid by ListThreads.
+  bool GetFPRegisters(int pid, user_fpregs_struct *regs) const;
+
+  // Get all the extended floating-point registers. May not work on all
+  // machines.
+  // The caller must get the thread pid by ListThreads.
+  bool GetFPXRegisters(int pid, user_fpxregs_struct *regs) const;
+
+  // Get the debug registers.
+  // The caller must get the thread pid by ListThreads.
+  bool GetDebugRegisters(int pid, DebugRegs *regs) const;
+
+  // Get the stack memory dump.
+  int GetThreadStackDump(uintptr_t current_ebp,
+                         uintptr_t current_esp,
+                         void *buf,
+                         int buf_size) const;
+
+  // Get the module count of the current process.
+  int GetModuleCount() const;
+
+  // Get the mapped modules in the address space.
+  // Whenever a module is found, the callback will be invoked to process the
+  // information.
+  // Return how may modules are found.
+  int ListModules(CallbackParam<ModuleCallback> *callback_param) const;
+
+  // Get the bottom of the stack from ebp.
+  uintptr_t GetThreadStackBottom(uintptr_t current_esp) const;
+
+ private:
+  // This callback will run when a new thread has been found.
+  typedef bool (*PidCallback)(int pid, void *context);
+
+  // Read thread information from /proc/$pid/task.
+  // Whenever a thread has been found, and callback will be invoked with
+  // the pid of the thread.
+  // Return number of threads found.
+  // Return -1 means the directory doesn't exist.
+  int IterateProcSelfTask(int pid,
+                          CallbackParam<PidCallback> *callback_param) const;
+
+  // Check if the address is a valid virtual address.
+  bool IsAddressMapped(uintptr_t address) const;
+
+ private:
+  // The pid of the process we are listing threads.
+  int pid_;
+
+  // Mark if we have suspended the threads.
+  bool threads_suspened_;
+};
+
+}  // namespace google_breakpad
+
+#endif  // CLIENT_LINUX_HANDLER_LINUX_THREAD_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread_test.cc
@@ -0,0 +1,224 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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 <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "client/linux/handler/linux_thread.h"
+
+using namespace google_breakpad;
+
+// Thread use this to see if it should stop working.
+static bool should_exit = false;
+
+static void foo2(int *a) {
+  // Stack variable, used for debugging stack dumps.
+  int c = 0xcccccccc;
+  c = c;
+  while (!should_exit)
+    sleep(1);
+}
+
+static void foo() {
+  // Stack variable, used for debugging stack dumps.
+  int a = 0xaaaaaaaa;
+  foo2(&a);
+}
+
+static void *thread_main(void *) {
+  // Stack variable, used for debugging stack dumps.
+  int b = 0xbbbbbbbb;
+  b = b;
+  while (!should_exit) {
+    foo();
+  }
+  return NULL;
+}
+
+static void CreateThreads(int num) {
+  pthread_t handle;
+  for (int i = 0; i < num; i++) {
+    if (0 != pthread_create(&handle, NULL, thread_main, NULL))
+      fprintf(stderr, "Failed to create thread.\n");
+    else
+      pthread_detach(handle);
+  }
+}
+
+static bool ProcessOneModule(const struct ModuleInfo &module_info,
+                             void *context) {
+  printf("0x%x[%8d]         %s\n", module_info.start_addr, module_info.size,
+         module_info.name);
+  return true;
+}
+
+static bool ProcessOneThread(const struct ThreadInfo &thread_info,
+                             void *context) {
+  printf("\n\nPID: %d, TGID: %d, PPID: %d\n",
+         thread_info.pid,
+         thread_info.tgid,
+         thread_info.ppid);
+
+  struct user_regs_struct regs;
+  struct user_fpregs_struct fp_regs;
+  struct user_fpxregs_struct fpx_regs;
+  struct DebugRegs dbg_regs;
+
+  LinuxThread *threads = reinterpret_cast<LinuxThread *>(context);
+  memset(&regs, 0, sizeof(regs));
+  if (threads->GetRegisters(thread_info.pid, &regs)) {
+    printf("  gs                           = 0x%lx\n", regs.xgs);
+    printf("  fs                           = 0x%lx\n", regs.xfs);
+    printf("  es                           = 0x%lx\n", regs.xes);
+    printf("  ds                           = 0x%lx\n", regs.xds);
+    printf("  edi                          = 0x%lx\n", regs.edi);
+    printf("  esi                          = 0x%lx\n", regs.esi);
+    printf("  ebx                          = 0x%lx\n", regs.ebx);
+    printf("  edx                          = 0x%lx\n", regs.edx);
+    printf("  ecx                          = 0x%lx\n", regs.ecx);
+    printf("  eax                          = 0x%lx\n", regs.eax);
+    printf("  ebp                          = 0x%lx\n", regs.ebp);
+    printf("  eip                          = 0x%lx\n", regs.eip);
+    printf("  cs                           = 0x%lx\n", regs.xcs);
+    printf("  eflags                       = 0x%lx\n", regs.eflags);
+    printf("  esp                          = 0x%lx\n", regs.esp);
+    printf("  ss                           = 0x%lx\n", regs.xss);
+  } else {
+    fprintf(stderr, "ERROR: Failed to get general purpose registers\n");
+  }
+  memset(&fp_regs, 0, sizeof(fp_regs));
+  if (threads->GetFPRegisters(thread_info.pid, &fp_regs)) {
+    printf("\n Floating point registers:\n");
+    printf("  fctl                         = 0x%lx\n", fp_regs.cwd);
+    printf("  fstat                        = 0x%lx\n", fp_regs.swd);
+    printf("  ftag                         = 0x%lx\n", fp_regs.twd);
+    printf("  fioff                        = 0x%lx\n", fp_regs.fip);
+    printf("  fiseg                        = 0x%lx\n", fp_regs.fcs);
+    printf("  fooff                        = 0x%lx\n", fp_regs.foo);
+    printf("  foseg                        = 0x%lx\n", fp_regs.fos);
+    int st_space_size = sizeof(fp_regs.st_space) / sizeof(fp_regs.st_space[0]);
+    printf("  st_space[%2d]                 = 0x", st_space_size);
+    for (int i = 0; i < st_space_size; ++i)
+      printf("%02lx", fp_regs.st_space[i]);
+    printf("\n");
+  } else {
+    fprintf(stderr, "ERROR: Failed to get floating-point registers\n");
+  }
+  memset(&fpx_regs, 0, sizeof(fpx_regs));
+  if (threads->GetFPXRegisters(thread_info.pid, &fpx_regs)) {
+    printf("\n Extended floating point registers:\n");
+    printf("  fctl                         = 0x%x\n", fpx_regs.cwd);
+    printf("  fstat                        = 0x%x\n", fpx_regs.swd);
+    printf("  ftag                         = 0x%x\n", fpx_regs.twd);
+    printf("  fioff                        = 0x%lx\n", fpx_regs.fip);
+    printf("  fiseg                        = 0x%lx\n", fpx_regs.fcs);
+    printf("  fooff                        = 0x%lx\n", fpx_regs.foo);
+    printf("  foseg                        = 0x%lx\n", fpx_regs.fos);
+    printf("  fop                          = 0x%x\n", fpx_regs.fop);
+    printf("  mxcsr                        = 0x%lx\n", fpx_regs.mxcsr);
+    int space_size = sizeof(fpx_regs.st_space) / sizeof(fpx_regs.st_space[0]);
+    printf("  st_space[%2d]                 = 0x", space_size);
+    for (int i = 0; i < space_size; ++i)
+      printf("%02lx", fpx_regs.st_space[i]);
+    printf("\n");
+    space_size = sizeof(fpx_regs.xmm_space) / sizeof(fpx_regs.xmm_space[0]);
+    printf("  xmm_space[%2d]                = 0x", space_size);
+    for (int i = 0; i < space_size; ++i)
+      printf("%02lx", fpx_regs.xmm_space[i]);
+    printf("\n");
+  }
+  if (threads->GetDebugRegisters(thread_info.pid, &dbg_regs)) {
+    printf("\n Debug registers:\n");
+    printf("  dr0                          = 0x%x\n", dbg_regs.dr0);
+    printf("  dr1                          = 0x%x\n", dbg_regs.dr1);
+    printf("  dr2                          = 0x%x\n", dbg_regs.dr2);
+    printf("  dr3                          = 0x%x\n", dbg_regs.dr3);
+    printf("  dr4                          = 0x%x\n", dbg_regs.dr4);
+    printf("  dr5                          = 0x%x\n", dbg_regs.dr5);
+    printf("  dr6                          = 0x%x\n", dbg_regs.dr6);
+    printf("  dr7                          = 0x%x\n", dbg_regs.dr7);
+    printf("\n");
+  }
+  if (regs.esp != 0) {
+    // Print the stack content.
+    int size = 1024 * 2;
+    char *buf = new char[size];
+    size = threads->GetThreadStackDump(regs.ebp,
+                                       regs.esp,
+                                      (void*)buf, size);
+    printf(" Stack content:                 = 0x");
+    size /= sizeof(unsigned long);
+    unsigned long *p_buf = (unsigned long *)(buf);
+    for (int i = 0; i < size; i += 1)
+      printf("%.8lx ", p_buf[i]);
+    delete []buf;
+    printf("\n");
+  }
+  return true;
+}
+
+static int PrintAllThreads(void *argument) {
+  int pid = (int)argument;
+
+  LinuxThread threads(pid);
+  int total_thread = threads.SuspendAllThreads();
+  printf("There are %d threads in the process: %d\n", total_thread, pid);
+  int total_module = threads.GetModuleCount();
+  printf("There are %d modules in the process: %d\n", total_module, pid);
+  CallbackParam<ModuleCallback> module_callback(ProcessOneModule, &threads);
+  threads.ListModules(&module_callback);
+  CallbackParam<ThreadCallback> thread_callback(ProcessOneThread, &threads);
+  threads.ListThreads(&thread_callback);
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  int pid = getpid();
+  printf("Main thread is %d\n", pid);
+  CreateThreads(1);
+  // Create stack for the process.
+  char *stack = new char[1024 * 100];
+  int cloned_pid = clone(PrintAllThreads, stack + 1024 * 100,
+                           CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
+                           (void*)getpid());
+  waitpid(cloned_pid, NULL, __WALL);
+  should_exit = true;
+  printf("Test finished.\n");
+
+  delete []stack;
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.cc
@@ -0,0 +1,772 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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 <fcntl.h>
+#include <pthread.h>
+#include <asm/sigcontext.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+
+#include <cstdlib>
+#include <ctime>
+
+#include "common/linux/file_id.h"
+#include "client/linux/handler/linux_thread.h"
+#include "client/minidump_file_writer.h"
+#include "client/minidump_file_writer-inl.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "client/linux/handler/minidump_generator.h"
+
+#ifndef CLONE_UNTRACED
+#define CLONE_UNTRACED 0x00800000
+#endif
+
+// This unnamed namespace contains helper functions.
+namespace {
+
+using namespace google_breakpad;
+
+// Argument for the writer function.
+struct WriterArgument {
+  MinidumpFileWriter *minidump_writer;
+
+  // Context for the callback.
+  void *version_context;
+
+  // Pid of the thread who called WriteMinidumpToFile
+  int requester_pid;
+
+  // The stack bottom of the thread which caused the dump.
+  // Mainly used to find the thread id of the crashed thread since signal
+  // handler may not be called in the thread who caused it.
+  uintptr_t crashed_stack_bottom;
+
+  // Pid of the crashing thread.
+  int crashed_pid;
+
+  // Signal number when crash happed. Can be 0 if this is a requested dump.
+  int signo;
+
+  // Signal contex when crash happed. Can be NULL if this is a requested dump.
+  const struct sigcontext *sig_ctx;
+
+  // Used to get information about the threads.
+  LinuxThread *thread_lister;
+};
+
+// Holding context information for the callback of finding the crashing thread.
+struct FindCrashThreadContext {
+  const LinuxThread *thread_lister;
+  uintptr_t crashing_stack_bottom;
+  int crashing_thread_pid;
+
+  FindCrashThreadContext() :
+    thread_lister(NULL),
+    crashing_stack_bottom(0UL),
+    crashing_thread_pid(-1) {
+  }
+};
+
+// Callback for list threads.
+// It will compare the stack bottom of the provided thread with the stack
+// bottom of the crashed thread, it they are eqaul, this is thread is the one
+// who crashed.
+bool IsThreadCrashedCallback(const ThreadInfo &thread_info, void *context) {
+  FindCrashThreadContext *crashing_context =
+    static_cast<FindCrashThreadContext *>(context);
+  const LinuxThread *thread_lister = crashing_context->thread_lister;
+  struct user_regs_struct regs;
+  if (thread_lister->GetRegisters(thread_info.pid, &regs)) {
+    uintptr_t last_ebp = regs.ebp;
+    uintptr_t stack_bottom = thread_lister->GetThreadStackBottom(last_ebp);
+    if (stack_bottom > last_ebp &&
+        stack_bottom == crashing_context->crashing_stack_bottom) {
+      // Got it. Stop iteration.
+      crashing_context->crashing_thread_pid = thread_info.pid;
+      return false;
+    }
+  }
+  return true;
+}
+
+// Find the crashing thread id.
+// This is done based on stack bottom comparing.
+int FindCrashingThread(uintptr_t crashing_stack_bottom,
+                       int requester_pid,
+                       const LinuxThread *thread_lister) {
+  FindCrashThreadContext context;
+  context.thread_lister = thread_lister;
+  context.crashing_stack_bottom = crashing_stack_bottom;
+  CallbackParam<ThreadCallback> callback_param(IsThreadCrashedCallback,
+                                               &context);
+  thread_lister->ListThreads(&callback_param);
+  return context.crashing_thread_pid;
+}
+
+// Write the thread stack info minidump.
+bool WriteThreadStack(uintptr_t last_ebp,
+                      uintptr_t last_esp,
+                      const LinuxThread *thread_lister,
+                      UntypedMDRVA *memory,
+                      MDMemoryDescriptor *loc) {
+  // Maximum stack size for a thread.
+  uintptr_t stack_bottom = thread_lister->GetThreadStackBottom(last_ebp);
+  if (stack_bottom > last_esp) {
+    int size = stack_bottom - last_esp;
+    if (size > 0) {
+      if (!memory->Allocate(size))
+        return false;
+      memory->Copy(reinterpret_cast<void*>(last_esp), size);
+      loc->start_of_memory_range = 0 | last_esp;
+      loc->memory = memory->location();
+    }
+    return true;
+  }
+  return false;
+}
+
+// Write CPU context based on signal context.
+bool WriteContext(MDRawContextX86 *context, const struct sigcontext *sig_ctx,
+                  const DebugRegs *debug_regs) {
+  assert(sig_ctx != NULL);
+  context->context_flags = MD_CONTEXT_X86_FULL;
+  context->gs = sig_ctx->gs;
+  context->fs = sig_ctx->fs;
+  context->es = sig_ctx->es;
+  context->ds = sig_ctx->ds;
+  context->cs = sig_ctx->cs;
+  context->ss = sig_ctx->ss;
+  context->edi = sig_ctx->edi;
+  context->esi = sig_ctx->esi;
+  context->ebp = sig_ctx->ebp;
+  context->esp = sig_ctx->esp;
+  context->ebx = sig_ctx->ebx;
+  context->edx = sig_ctx->edx;
+  context->ecx = sig_ctx->ecx;
+  context->eax = sig_ctx->eax;
+  context->eip = sig_ctx->eip;
+  context->eflags = sig_ctx->eflags;
+  if (sig_ctx->fpstate != NULL) {
+    context->context_flags = MD_CONTEXT_X86_FULL |
+      MD_CONTEXT_X86_FLOATING_POINT;
+    context->float_save.control_word = sig_ctx->fpstate->cw;
+    context->float_save.status_word = sig_ctx->fpstate->sw;
+    context->float_save.tag_word = sig_ctx->fpstate->tag;
+    context->float_save.error_offset = sig_ctx->fpstate->ipoff;
+    context->float_save.error_selector = sig_ctx->fpstate->cssel;
+    context->float_save.data_offset = sig_ctx->fpstate->dataoff;
+    context->float_save.data_selector = sig_ctx->fpstate->datasel;
+    memcpy(context->float_save.register_area, sig_ctx->fpstate->_st,
+           sizeof(context->float_save.register_area));
+  }
+
+  if (debug_regs != NULL) {
+    context->context_flags |= MD_CONTEXT_X86_DEBUG_REGISTERS;
+    context->dr0 = debug_regs->dr0;
+    context->dr1 = debug_regs->dr1;
+    context->dr2 = debug_regs->dr2;
+    context->dr3 = debug_regs->dr3;
+    context->dr6 = debug_regs->dr6;
+    context->dr7 = debug_regs->dr7;
+  }
+  return true;
+}
+
+// Write CPU context based on provided registers.
+bool WriteContext(MDRawContextX86 *context,
+                  const struct user_regs_struct *regs,
+                  const struct user_fpregs_struct *fp_regs,
+                  const DebugRegs *dbg_regs) {
+  if (!context || !regs)
+    return false;
+
+  context->context_flags = MD_CONTEXT_X86_FULL;
+
+  context->cs = regs->xcs;
+  context->ds = regs->xds;
+  context->es = regs->xes;
+  context->fs = regs->xfs;
+  context->gs = regs->xgs;
+  context->ss = regs->xss;
+  context->edi = regs->edi;
+  context->esi = regs->esi;
+  context->ebx = regs->ebx;
+  context->edx = regs->edx;
+  context->ecx = regs->ecx;
+  context->eax = regs->eax;
+  context->ebp = regs->ebp;
+  context->eip = regs->eip;
+  context->esp = regs->esp;
+  context->eflags = regs->eflags;
+
+  if (dbg_regs != NULL) {
+    context->context_flags |= MD_CONTEXT_X86_DEBUG_REGISTERS;
+    context->dr0 = dbg_regs->dr0;
+    context->dr1 = dbg_regs->dr1;
+    context->dr2 = dbg_regs->dr2;
+    context->dr3 = dbg_regs->dr3;
+    context->dr6 = dbg_regs->dr6;
+    context->dr7 = dbg_regs->dr7;
+  }
+
+  if (fp_regs != NULL) {
+    context->context_flags |= MD_CONTEXT_X86_FLOATING_POINT;
+    context->float_save.control_word = fp_regs->cwd;
+    context->float_save.status_word = fp_regs->swd;
+    context->float_save.tag_word = fp_regs->twd;
+    context->float_save.error_offset = fp_regs->fip;
+    context->float_save.error_selector = fp_regs->fcs;
+    context->float_save.data_offset = fp_regs->foo;
+    context->float_save.data_selector = fp_regs->fos;
+    context->float_save.data_selector = fp_regs->fos;
+
+    memcpy(context->float_save.register_area, fp_regs->st_space,
+           sizeof(context->float_save.register_area));
+  }
+  return true;
+}
+
+// Write information about a crashed thread.
+// When a thread 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 WriteCrashedThreadStream(MinidumpFileWriter *minidump_writer,
+                       const WriterArgument *writer_args,
+                       const ThreadInfo &thread_info,
+                       MDRawThread *thread) {
+  assert(writer_args->sig_ctx != NULL);
+
+  thread->thread_id = thread_info.pid;
+
+  UntypedMDRVA memory(minidump_writer);
+  if (!WriteThreadStack(writer_args->sig_ctx->ebp,
+                   writer_args->sig_ctx->esp,
+                   writer_args->thread_lister,
+                   &memory,
+                   &thread->stack))
+    return false;
+
+  TypedMDRVA<MDRawContextX86> context(minidump_writer);
+  if (!context.Allocate())
+    return false;
+  thread->thread_context = context.location();
+  memset(context.get(), 0, sizeof(MDRawContextX86));
+  return WriteContext(context.get(), writer_args->sig_ctx, NULL);
+}
+
+// Write information about a thread.
+// This function only processes thread running normally at the crash.
+bool WriteThreadStream(MinidumpFileWriter *minidump_writer,
+                       const LinuxThread *thread_lister,
+                       const ThreadInfo &thread_info,
+                       MDRawThread *thread) {
+  thread->thread_id = thread_info.pid;
+
+  struct user_regs_struct regs;
+  memset(&regs, 0, sizeof(regs));
+  if (!thread_lister->GetRegisters(thread_info.pid, &regs)) {
+    perror(NULL);
+    return false;
+  }
+
+  UntypedMDRVA memory(minidump_writer);
+  if (!WriteThreadStack(regs.ebp,
+                   regs.esp,
+                   thread_lister,
+                   &memory,
+                   &thread->stack))
+    return false;
+
+  struct user_fpregs_struct fp_regs;
+  DebugRegs dbg_regs;
+  memset(&fp_regs, 0, sizeof(fp_regs));
+  // Get all the registers.
+  thread_lister->GetFPRegisters(thread_info.pid, &fp_regs);
+  thread_lister->GetDebugRegisters(thread_info.pid, &dbg_regs);
+
+  // Write context
+  TypedMDRVA<MDRawContextX86> context(minidump_writer);
+  if (!context.Allocate())
+    return false;
+  thread->thread_context = context.location();
+  memset(context.get(), 0, sizeof(MDRawContextX86));
+  return WriteContext(context.get(), &regs, &fp_regs, &dbg_regs);
+}
+
+bool WriteCPUInformation(MDRawSystemInfo *sys_info) {
+  const char *proc_cpu_path = "/proc/cpuinfo";
+  char line[128];
+
+  struct CpuInfoEntry {
+    const char *info_name;
+    int value;
+  } cpu_info_table[] = {
+    { "processor", -1 },
+    { "model", 0 },
+    { "stepping",  0 },
+    { "cpuid level", 0 },
+    { NULL, -1 },
+  };
+
+  FILE *fp = fopen(proc_cpu_path, "r");
+  if (fp != NULL) {
+    while (fgets(line, sizeof(line), fp)) {
+      CpuInfoEntry *entry = &cpu_info_table[0];
+      while (entry->info_name != NULL) {
+        if (!strncmp(line, entry->info_name, strlen(entry->info_name))) {
+          char *value = strchr(line, ':');
+          value++;
+          if (value != NULL)
+            sscanf(value, " %d", &(entry->value));
+        }
+        entry++;
+      }
+    }
+    fclose(fp);
+  }
+
+  // /proc/cpuinfo contains cpu id, change it into number by adding one.
+  cpu_info_table[0].value++;
+
+  sys_info->number_of_processors = cpu_info_table[0].value;
+  sys_info->processor_level      = cpu_info_table[3].value;
+  sys_info->processor_revision   = cpu_info_table[1].value << 8 |
+                                   cpu_info_table[2].value;
+
+  sys_info->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN;
+  struct utsname uts;
+  if (uname(&uts) == 0) {
+    // Match i*86 and x86* as X86 architecture.
+    if ((strstr(uts.machine, "x86") == uts.machine) ||
+        (strlen(uts.machine) == 4 &&
+         uts.machine[0] == 'i' &&
+         uts.machine[2] == '8' &&
+         uts.machine[3] == '6'))
+      sys_info->processor_architecture = MD_CPU_ARCHITECTURE_X86;
+  }
+  return true;
+}
+
+bool WriteOSInformation(MinidumpFileWriter *minidump_writer,
+                        MDRawSystemInfo *sys_info) {
+  sys_info->platform_id = MD_OS_LINUX;
+
+  struct utsname uts;
+  if (uname(&uts) == 0) {
+    char os_version[512];
+    size_t space_left = sizeof(os_version);
+    memset(os_version, 0, space_left);
+    const char *os_info_table[] = {
+      uts.sysname,
+      uts.release,
+      uts.version,
+      uts.machine,
+      "GNU/Linux",
+      NULL
+    };
+    for (const char **cur_os_info = os_info_table;
+         *cur_os_info != NULL;
+         cur_os_info++) {
+      if (cur_os_info != os_info_table && space_left > 1) {
+        strcat(os_version, " ");
+        space_left--;
+      }
+      if (space_left > strlen(*cur_os_info)) {
+        strcat(os_version, *cur_os_info);
+        space_left -= strlen(*cur_os_info);
+      } else {
+        break;
+      }
+    }
+
+    MDLocationDescriptor location;
+    if (!minidump_writer->WriteString(os_version, 0, &location))
+      return false;
+    sys_info->csd_version_rva = location.rva;
+  }
+  return true;
+}
+
+// Callback context for get writting thread information.
+struct ThreadInfoCallbackCtx {
+  MinidumpFileWriter *minidump_writer;
+  const WriterArgument *writer_args;
+  TypedMDRVA<MDRawThreadList> *list;
+  int thread_index;
+};
+
+// Callback run for writing threads information in the process.
+bool ThreadInfomationCallback(const ThreadInfo &thread_info,
+                                 void *context) {
+  ThreadInfoCallbackCtx *callback_context =
+    static_cast<ThreadInfoCallbackCtx *>(context);
+  bool success = true;
+  MDRawThread thread;
+  memset(&thread, 0, sizeof(MDRawThread));
+  if (thread_info.pid != callback_context->writer_args->crashed_pid ||
+      callback_context->writer_args->sig_ctx == NULL) {
+    success = WriteThreadStream(callback_context->minidump_writer,
+                           callback_context->writer_args->thread_lister,
+                           thread_info, &thread);
+  } else {
+    success = WriteCrashedThreadStream(callback_context->minidump_writer,
+                                       callback_context->writer_args,
+                                       thread_info, &thread);
+  }
+  if (success) {
+    callback_context->list->CopyIndexAfterObject(
+        callback_context->thread_index++,
+        &thread, sizeof(MDRawThread));
+  }
+  return success;
+}
+
+// Stream writers
+bool WriteThreadListStream(MinidumpFileWriter *minidump_writer,
+                           const WriterArgument *writer_args,
+                           MDRawDirectory *dir) {
+  // Get the thread information.
+  const LinuxThread *thread_lister = writer_args->thread_lister;
+  int thread_count = thread_lister->GetThreadCount();
+  if (thread_count < 0)
+    return false;
+  TypedMDRVA<MDRawThreadList> list(minidump_writer);
+  if (!list.AllocateObjectAndArray(thread_count, sizeof(MDRawThread)))
+    return false;
+  dir->stream_type = MD_THREAD_LIST_STREAM;
+  dir->location = list.location();
+  list.get()->number_of_threads = thread_count;
+
+  ThreadInfoCallbackCtx context;
+  context.minidump_writer = minidump_writer;
+  context.writer_args = writer_args;
+  context.list = &list;
+  context.thread_index = 0;
+  CallbackParam<ThreadCallback> callback_param(ThreadInfomationCallback,
+                                               &context);
+  int written = thread_lister->ListThreads(&callback_param);
+  return written == thread_count;
+}
+
+bool WriteCVRecord(MinidumpFileWriter *minidump_writer,
+                   MDRawModule *module,
+                   const char *module_path) {
+  TypedMDRVA<MDCVInfoPDB70> cv(minidump_writer);
+
+  // Only return the last path component of the full module path
+  const char *module_name = strrchr(module_path, '/');
+  // Increment past the slash
+  if (module_name)
+    ++module_name;
+  else
+    module_name = "<Unknown>";
+
+  size_t module_name_length = strlen(module_name);
+  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))
+    return false;
+
+  module->cv_record = cv.location();
+  MDCVInfoPDB70 *cv_ptr = cv.get();
+  memset(cv_ptr, 0, sizeof(MDCVInfoPDB70));
+  cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE;
+  cv_ptr->age = 0;
+
+  // Get the module identifier
+  FileID file_id(module_path);
+  unsigned char identifier[16];
+
+  if (file_id.ElfFileIdentifier(identifier)) {
+    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];
+    cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7];
+    cv_ptr->signature.data4[0] = identifier[8];
+    cv_ptr->signature.data4[1] = identifier[9];
+    cv_ptr->signature.data4[2] = identifier[10];
+    cv_ptr->signature.data4[3] = identifier[11];
+    cv_ptr->signature.data4[4] = identifier[12];
+    cv_ptr->signature.data4[5] = identifier[13];
+    cv_ptr->signature.data4[6] = identifier[14];
+    cv_ptr->signature.data4[7] = identifier[15];
+  }
+  return true;
+}
+
+struct ModuleInfoCallbackCtx {
+  MinidumpFileWriter *minidump_writer;
+  const WriterArgument *writer_args;
+  TypedMDRVA<MDRawModuleList> *list;
+  int module_index;
+};
+
+bool ModuleInfoCallback(const ModuleInfo &module_info,
+                           void *context) {
+  ModuleInfoCallbackCtx *callback_context =
+    static_cast<ModuleInfoCallbackCtx *>(context);
+  // Skip those modules without name, or those that are not modules.
+  if (strlen(module_info.name) == 0 ||
+      !strchr(module_info.name, '/'))
+    return true;
+
+  MDRawModule module;
+  memset(&module, 0, sizeof(module));
+  MDLocationDescriptor loc;
+  if (!callback_context->minidump_writer->WriteString(module_info.name, 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 (!WriteCVRecord(callback_context->minidump_writer, &module,
+                     module_info.name))
+    return false;
+  callback_context->list->CopyIndexAfterObject(
+      callback_context->module_index++, &module, MD_MODULE_SIZE);
+  return true;
+}
+
+bool WriteModuleListStream(MinidumpFileWriter *minidump_writer,
+                           const WriterArgument *writer_args,
+                           MDRawDirectory *dir) {
+  TypedMDRVA<MDRawModuleList> list(minidump_writer);
+  int module_count  = writer_args->thread_lister->GetModuleCount();
+  if (module_count <= 0 ||
+      !list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE))
+    return false;
+  dir->stream_type = MD_MODULE_LIST_STREAM;
+  dir->location = list.location();
+  list.get()->number_of_modules = module_count;
+  ModuleInfoCallbackCtx context;
+  context.minidump_writer = minidump_writer;
+  context.writer_args = writer_args;
+  context.list = &list;
+  context.module_index = 0;
+  CallbackParam<ModuleCallback> callback(ModuleInfoCallback, &context);
+  return writer_args->thread_lister->ListModules(&callback) == module_count;
+}
+
+bool WriteSystemInfoStream(MinidumpFileWriter *minidump_writer,
+                           const WriterArgument *writer_args,
+                           MDRawDirectory *dir) {
+  TypedMDRVA<MDRawSystemInfo> sys_info(minidump_writer);
+  if (!sys_info.Allocate())
+    return false;
+  dir->stream_type = MD_SYSTEM_INFO_STREAM;
+  dir->location = sys_info.location();
+
+  return WriteCPUInformation(sys_info.get()) &&
+         WriteOSInformation(minidump_writer, sys_info.get());
+}
+
+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(minidump_writer);
+  if (!exception.Allocate())
+    return false;
+
+  dir->stream_type = MD_EXCEPTION_STREAM;
+  dir->location = exception.location();
+  exception.get()->thread_id = writer_args->crashed_pid;
+  exception.get()->exception_record.exception_code = writer_args->signo;
+  exception.get()->exception_record.exception_flags = 0;
+  if (writer_args->sig_ctx != NULL) {
+    exception.get()->exception_record.exception_address =
+      writer_args->sig_ctx->eip;
+  } else {
+    return true;
+  }
+
+  // Write context of the exception.
+  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(), writer_args->sig_ctx, NULL);
+}
+
+bool WriteMiscInfoStream(MinidumpFileWriter *minidump_writer,
+                           const WriterArgument *writer_args,
+                           MDRawDirectory *dir) {
+  TypedMDRVA<MDRawMiscInfo> info(minidump_writer);
+  if (!info.Allocate())
+    return false;
+
+  dir->stream_type = MD_MISC_INFO_STREAM;
+  dir->location = info.location();
+  info.get()->size_of_info = sizeof(MDRawMiscInfo);
+  info.get()->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID;
+  info.get()->process_id = writer_args->requester_pid;
+
+  return true;
+}
+
+bool WriteBreakpadInfoStream(MinidumpFileWriter *minidump_writer,
+                           const WriterArgument *writer_args,
+                           MDRawDirectory *dir) {
+  TypedMDRVA<MDRawBreakpadInfo> info(minidump_writer);
+  if (!info.Allocate())
+    return false;
+
+  dir->stream_type = MD_BREAKPAD_INFO_STREAM;
+  dir->location = info.location();
+
+  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 = writer_args->requester_pid;
+  return true;
+}
+
+// Prototype of writer functions.
+typedef bool (*WriteStringFN)(MinidumpFileWriter *,
+                              const WriterArgument *,
+                              MDRawDirectory *);
+
+// Function table to writer a full minidump.
+WriteStringFN writers[] = {
+  WriteThreadListStream,
+  WriteModuleListStream,
+  WriteSystemInfoStream,
+  WriteExceptionStream,
+  WriteMiscInfoStream,
+  WriteBreakpadInfoStream,
+};
+
+// Will call each writer function in the writers table.
+// It runs in a different process from the crashing process, but sharing
+// the same address space. This enables it to use ptrace functions.
+int Write(void *argument) {
+  WriterArgument *writer_args =
+    static_cast<WriterArgument *>(argument);
+
+  if (!writer_args->thread_lister->SuspendAllThreads())
+    return -1;
+
+  if (writer_args->sig_ctx != NULL) {
+    writer_args->crashed_stack_bottom =
+    writer_args->thread_lister->GetThreadStackBottom(writer_args->sig_ctx->ebp);
+    int crashed_pid =  FindCrashingThread(writer_args->crashed_stack_bottom,
+                                         writer_args->requester_pid,
+                                         writer_args->thread_lister);
+    if (crashed_pid > 0)
+      writer_args->crashed_pid = crashed_pid;
+  }
+
+
+  MinidumpFileWriter *minidump_writer = writer_args->minidump_writer;
+  TypedMDRVA<MDRawHeader> header(minidump_writer);
+  TypedMDRVA<MDRawDirectory> dir(minidump_writer);
+  if (!header.Allocate())
+    return 0;
+
+  int writer_count = sizeof(writers) / sizeof(writers[0]);
+  // Need directory space for all writers.
+  if (!dir.AllocateArray(writer_count))
+    return 0;
+  header.get()->signature = MD_HEADER_SIGNATURE;
+  header.get()->version = MD_HEADER_VERSION;
+  header.get()->time_date_stamp = time(NULL);
+  header.get()->stream_count = writer_count;
+  header.get()->stream_directory_rva = dir.position();
+
+  int dir_index = 0;
+  MDRawDirectory local_dir;
+  for (int i = 0; i < writer_count; ++i) {
+    if (writers[i](minidump_writer, writer_args, &local_dir))
+      dir.CopyIndex(dir_index++, &local_dir);
+  }
+
+  writer_args->thread_lister->ResumeAllThreads();
+  return 0;
+}
+
+}  // namespace
+
+namespace google_breakpad {
+
+MinidumpGenerator::MinidumpGenerator() {
+  AllocateStack();
+}
+
+MinidumpGenerator::~MinidumpGenerator() {
+}
+
+void MinidumpGenerator::AllocateStack() {
+  stack_.reset(new char[kStackSize]);
+}
+
+bool MinidumpGenerator::WriteMinidumpToFile(const char *file_pathname,
+                                   int signo,
+                                   const struct sigcontext *sig_ctx) const {
+  assert(file_pathname != NULL);
+  assert(stack_ != NULL);
+
+  if (stack_ == NULL || file_pathname == NULL)
+    return false;
+
+  MinidumpFileWriter minidump_writer;
+  if (minidump_writer.Open(file_pathname)) {
+    WriterArgument argument;
+    memset(&argument, 0, sizeof(argument));
+    LinuxThread thread_lister(getpid());
+    argument.thread_lister = &thread_lister;
+    argument.minidump_writer = &minidump_writer;
+    argument.requester_pid = getpid();
+    argument.crashed_pid = getpid();
+    argument.signo = signo;
+    argument.sig_ctx = sig_ctx;
+
+    int cloned_pid = clone(Write, stack_.get() + kStackSize,
+                           CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
+                           (void*)&argument);
+    waitpid(cloned_pid, NULL, __WALL);
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace google_breakpad
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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_LINUX_HANDLER_MINIDUMP_GENERATOR_H__
+#define CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "processor/scoped_ptr.h"
+
+struct sigcontext;
+
+namespace google_breakpad {
+
+//
+// MinidumpGenerator
+//
+// Write a minidump to file based on the signo and sig_ctx.
+// A minidump generator should be created before any exception happen.
+//
+class MinidumpGenerator {
+  public:
+   MinidumpGenerator();
+
+   ~MinidumpGenerator();
+
+   // Write minidump.
+   bool WriteMinidumpToFile(const char *file_pathname,
+                            int signo,
+                            const struct sigcontext *sig_ctx) const;
+  private:
+   // Allocate memory for stack.
+   void AllocateStack();
+
+  private:
+   // Stack size of the writer thread.
+   static const int kStackSize = 1024 * 1024;
+   scoped_array<char> stack_;
+};
+
+}  // namespace google_breakpad
+
+#endif   // CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_test.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Author: Li Liu
+//
+// 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 <pthread.h>
+#include <unistd.h>
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "client/linux/handler/minidump_generator.h"
+
+using namespace google_breakpad;
+
+// Thread use this to see if it should stop working.
+static bool should_exit = false;
+
+static void foo2(int arg) {
+  // Stack variable, used for debugging stack dumps.
+  int c = arg;
+  c = 0xcccccccc;
+  while (!should_exit)
+    sleep(1);
+}
+
+static void foo(int arg) {
+  // Stack variable, used for debugging stack dumps.
+  int b = arg;
+  b = 0xbbbbbbbb;
+  foo2(b);
+}
+
+static void *thread_main(void *) {
+  // Stack variable, used for debugging stack dumps.
+  int a = 0xaaaaaaaa;
+  foo(a);
+  return NULL;
+}
+
+static void CreateThread(int num) {
+  pthread_t h;
+  for (int i = 0; i < num; ++i) {
+    pthread_create(&h, NULL, thread_main, NULL);
+    pthread_detach(h);
+  }
+}
+
+int main(int argc, char *argv[]) {
+  CreateThread(10);
+  google_breakpad::MinidumpGenerator mg;
+  if (mg.WriteMinidumpToFile("minidump_test.out", -1, NULL))
+    printf("Succeeded written minidump\n");
+  else
+    printf("Failed to write minidump\n");
+  should_exit = true;
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc
@@ -0,0 +1,561 @@
+// 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.
+
+#include <map>
+#include <pthread.h>
+
+#include "client/mac/handler/exception_handler.h"
+#include "client/mac/handler/minidump_generator.h"
+
+namespace google_breakpad {
+
+using std::map;
+
+// These structures and techniques are illustrated in
+// Mac OS X Internals, Amit Singh, ch 9.7
+struct ExceptionMessage {
+  mach_msg_header_t           header;
+  mach_msg_body_t             body;
+  mach_msg_port_descriptor_t  thread;
+  mach_msg_port_descriptor_t  task;
+  NDR_record_t                ndr;
+  exception_type_t            exception;
+  mach_msg_type_number_t      code_count;
+  integer_t                   code[EXCEPTION_CODE_MAX];
+  char                        padding[512];
+};
+
+struct ExceptionParameters {
+  ExceptionParameters() : count(0) {}
+  mach_msg_type_number_t count;
+  exception_mask_t masks[EXC_TYPES_COUNT];
+  mach_port_t ports[EXC_TYPES_COUNT];
+  exception_behavior_t behaviors[EXC_TYPES_COUNT];
+  thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+};
+
+struct ExceptionReplyMessage {
+  mach_msg_header_t  header;
+  NDR_record_t       ndr;
+  kern_return_t      return_code;
+};
+
+// Only catch these three exceptions.  The other ones are nebulously defined
+// and may result in treating a non-fatal exception as fatal.
+exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS | 
+EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC;
+
+extern "C"
+{
+  // Forward declarations for functions that need "C" style compilation
+  boolean_t exc_server(mach_msg_header_t *request,
+                       mach_msg_header_t *reply);
+
+  kern_return_t catch_exception_raise(mach_port_t target_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 ForwardException(mach_port_t task,
+                                 mach_port_t failed_thread,
+                                 exception_type_t exception,
+                                 exception_data_t code,
+                                 mach_msg_type_number_t code_count);
+
+  kern_return_t exception_raise(mach_port_t target_port,
+                                mach_port_t failed_thread,
+                                mach_port_t task,
+                                exception_type_t exception,
+                                exception_data_t exception_code,
+                                mach_msg_type_number_t exception_code_count);
+
+  kern_return_t
+    exception_raise_state(mach_port_t target_port,
+                          mach_port_t failed_thread,
+                          mach_port_t task,
+                          exception_type_t exception,
+                          exception_data_t exception_code,
+                          mach_msg_type_number_t code_count,
+                          thread_state_flavor_t *target_flavor,
+                          thread_state_t thread_state,
+                          mach_msg_type_number_t thread_state_count,
+                          thread_state_t thread_state,
+                          mach_msg_type_number_t *thread_state_count);
+
+  kern_return_t
+    exception_raise_state_identity(mach_port_t target_port,
+                                   mach_port_t failed_thread,
+                                   mach_port_t task,
+                                   exception_type_t exception,
+                                   exception_data_t exception_code,
+                                   mach_msg_type_number_t exception_code_count,
+                                   thread_state_flavor_t *target_flavor,
+                                   thread_state_t thread_state,
+                                   mach_msg_type_number_t thread_state_count,
+                                   thread_state_t thread_state,
+                                   mach_msg_type_number_t *thread_state_count);
+}
+
+ExceptionHandler::ExceptionHandler(const string &dump_path,
+                                   FilterCallback filter,
+                                   MinidumpCallback callback,
+                                   void *callback_context,
+                                   bool install_handler)
+    : dump_path_(),
+      filter_(filter),
+      callback_(callback),
+      callback_context_(callback_context),
+      handler_thread_(NULL),
+      handler_port_(0),
+      previous_(NULL),
+      installed_exception_handler_(false),
+      is_in_teardown_(false),
+      last_minidump_write_result_(false),
+      use_minidump_write_mutex_(false) {
+  // This will update to the ID and C-string pointers
+  set_dump_path(dump_path);
+  MinidumpGenerator::GatherSystemInformation();
+  Setup(install_handler);
+}
+
+ExceptionHandler::~ExceptionHandler() {
+  Teardown();
+}
+
+bool ExceptionHandler::WriteMinidump() {
+  // If we're currently writing, just return
+  if (use_minidump_write_mutex_)
+    return false;
+
+  use_minidump_write_mutex_ = true;
+  last_minidump_write_result_ = false;
+
+  // Lock the mutex.  Since we just created it, this will return immediately.
+  if (pthread_mutex_lock(&minidump_write_mutex_) == 0) {
+    // Send an empty message to the handle port so that a minidump will
+    // be written
+    SendEmptyMachMessage();
+
+    // Wait for the minidump writer to complete its writing.  It will unlock
+    // the mutex when completed
+    pthread_mutex_lock(&minidump_write_mutex_);
+  }
+  
+  use_minidump_write_mutex_ = false;
+  UpdateNextID();
+  return last_minidump_write_result_;
+}
+
+// static
+bool ExceptionHandler::WriteMinidump(const string &dump_path,
+                                     MinidumpCallback callback,
+                                     void *callback_context) {
+  ExceptionHandler handler(dump_path, NULL, callback, callback_context, false);
+  return handler.WriteMinidump();
+}
+
+bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
+                                                  int exception_code,
+                                                  mach_port_t thread_name) {
+  bool result = false;
+  string minidump_id;
+
+  // Putting the MinidumpGenerator in its own context will ensure that the
+  // destructor is executed, closing the newly created minidump file.
+  if (!dump_path_.empty()) {
+    MinidumpGenerator md;
+    if (exception_type && exception_code) {
+      // If this is a real exception, give the filter (if any) a chance to
+      // decided if this should be sent
+      if (filter_ && !filter_(callback_context_))
+        return false;
+
+      md.SetExceptionInformation(exception_type, exception_code, thread_name);
+    }
+
+    result = md.Write(next_minidump_path_c_);
+  }
+
+  // Call user specified callback (if any)
+  if (callback_) {
+    // If the user callback returned true and we're handling an exception
+    // (rather than just writing out the file), then we should exit without
+    // forwarding the exception to the next handler.
+    if (callback_(dump_path_c_, next_minidump_id_c_, callback_context_, 
+                  result)) {
+      if (exception_type && exception_code)
+        exit(exception_type);
+    }
+  }
+
+  return result;
+}
+
+kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
+                               exception_type_t exception,
+                               exception_data_t code,
+                               mach_msg_type_number_t code_count) {
+  // At this time, we should have called Uninstall() on the exception handler
+  // so that the current exception ports are the ones that we should be 
+  // forwarding to.
+  ExceptionParameters current;
+  
+  current.count = EXC_TYPES_COUNT;
+  mach_port_t current_task = mach_task_self();
+  kern_return_t result = task_get_exception_ports(current_task, 
+                                                  s_exception_mask,
+                                                  current.masks,
+                                                  &current.count,
+                                                  current.ports,
+                                                  current.behaviors,
+                                                  current.flavors);
+  
+  // Find the first exception handler that matches the exception
+  unsigned int found;
+  for (found = 0; found < current.count; ++found) {
+    if (current.masks[found] & (1 << exception)) {
+      break;
+    }
+  }
+
+  // Nothing to forward
+  if (found == current.count) {
+    fprintf(stderr, "** No previous ports for forwarding!! \n");
+    exit(KERN_FAILURE);
+  }
+
+  mach_port_t target_port = current.ports[found];
+  exception_behavior_t target_behavior = current.behaviors[found];
+  thread_state_flavor_t target_flavor = current.flavors[found];
+
+  mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
+  thread_state_data_t thread_state;
+  switch (target_behavior) {
+    case EXCEPTION_DEFAULT:
+      result = exception_raise(target_port, failed_thread, task, exception,
+                               code, code_count);
+      break;
+
+    case EXCEPTION_STATE:
+      result = thread_get_state(failed_thread, target_flavor, thread_state,
+                                &thread_state_count);
+      if (result == KERN_SUCCESS)
+        result = exception_raise_state(target_port, failed_thread, task,
+                                       exception, code,
+                                       code_count, &target_flavor,
+                                       thread_state, thread_state_count,
+                                       thread_state, &thread_state_count);
+      if (result == KERN_SUCCESS)
+        result = thread_set_state(failed_thread, target_flavor, thread_state,
+                                  thread_state_count);
+      break;
+
+    case EXCEPTION_STATE_IDENTITY:
+      result = thread_get_state(failed_thread, target_flavor, thread_state,
+                                &thread_state_count);
+      if (result == KERN_SUCCESS)
+        result = exception_raise_state_identity(target_port, failed_thread,
+                                                task, exception, code,
+                                                code_count, &target_flavor,
+                                                thread_state,
+                                                thread_state_count,
+                                                thread_state,
+                                                &thread_state_count);
+      if (result == KERN_SUCCESS)
+        result = thread_set_state(failed_thread, target_flavor, thread_state,
+                                  thread_state_count);
+      break;
+
+    default:
+      fprintf(stderr, "** Unknown exception behavior\n");
+      result = KERN_FAILURE;
+      break;
+  }
+
+  return result;
+}
+
+// Callback from exc_server()
+kern_return_t catch_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);
+}
+
+// static
+void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
+  ExceptionHandler *self =
+    reinterpret_cast<ExceptionHandler *>(exception_handler_class);
+  ExceptionMessage receive;
+
+  // Wait for the exception info
+  while (1) {
+    receive.header.msgh_local_port = self->handler_port_;
+    receive.header.msgh_size = sizeof(receive);
+    kern_return_t result = mach_msg(&(receive.header),
+                                    MACH_RCV_MSG | MACH_RCV_LARGE, 0,
+                                    sizeof(receive), self->handler_port_,
+                                    MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+    if (result == KERN_SUCCESS) {
+      // Uninstall our handler so that we don't get in a loop if the process of
+      // writing out a minidump causes an exception.  However, if the exception
+      // was caused by a fork'd process, don't uninstall things
+      if (receive.task.name == mach_task_self())
+        self->UninstallHandler();
+      
+      // If the actual exception code is zero, then we're calling this handler
+      // in a way that indicates that we want to either exit this thread or
+      // generate a minidump
+      //
+      // While reporting, all threads (except this one) must be suspended
+      // to avoid misleading stacks.  If appropriate they will be resumed
+      // afterwards.
+      if (!receive.exception) {
+        if (self->is_in_teardown_)
+          return NULL;
+
+        self->SuspendThreads();
+
+        // Write out the dump and save the result for later retrieval
+        self->last_minidump_write_result_ =
+          self->WriteMinidumpWithException(0, 0, 0);
+
+        self->ResumeThreads();
+
+        if (self->use_minidump_write_mutex_)
+          pthread_mutex_unlock(&self->minidump_write_mutex_);
+      } else {
+        // When forking a child process with the exception handler installed,
+        // if the child crashes, it will send the exception back to the parent
+        // process.  The check for task == self_task() ensures that only 
+        // exceptions that occur in the parent process are caught and 
+        // processed.
+        if (receive.task.name == mach_task_self()) {
+          self->SuspendThreads();
+          
+          // Generate the minidump with the exception data.
+          self->WriteMinidumpWithException(receive.exception, receive.code[0],
+                                           receive.thread.name);
+        
+          // Pass along the exception to the server, which will setup the 
+          // message and call catch_exception_raise() and put the KERN_SUCCESS
+          // into the reply.
+          ExceptionReplyMessage reply;
+          if (!exc_server(&receive.header, &reply.header))
+            exit(1);
+
+          // Send a reply and exit
+          result = mach_msg(&(reply.header), MACH_SEND_MSG,
+                            reply.header.msgh_size, 0, MACH_PORT_NULL,
+                            MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+        } else {
+          // An exception occurred in a child process 
+        }
+      }
+    }
+  }
+
+  return NULL;
+}
+
+bool ExceptionHandler::InstallHandler() {
+  try {
+    previous_ = new ExceptionParameters();
+  }
+  catch (std::bad_alloc) {
+    return false;
+  }
+
+  // Save the current exception ports so that we can forward to them
+  previous_->count = EXC_TYPES_COUNT;
+  mach_port_t current_task = mach_task_self();
+  kern_return_t result = task_get_exception_ports(current_task, 
+                                                  s_exception_mask,
+                                                  previous_->masks,
+                                                  &previous_->count,
+                                                  previous_->ports,
+                                                  previous_->behaviors,
+                                                  previous_->flavors);
+  
+  // Setup the exception ports on this task
+  if (result == KERN_SUCCESS)
+    result = task_set_exception_ports(current_task, s_exception_mask,
+                                      handler_port_, EXCEPTION_DEFAULT,
+                                      THREAD_STATE_NONE);
+
+  installed_exception_handler_ = (result == KERN_SUCCESS);
+
+  return installed_exception_handler_;
+}
+
+bool ExceptionHandler::UninstallHandler() {
+  kern_return_t result = KERN_SUCCESS;
+  
+  if (installed_exception_handler_) {
+    mach_port_t current_task = mach_task_self();
+    
+    // Restore the previous ports
+    for (unsigned int i = 0; i < previous_->count; ++i) {
+       result = task_set_exception_ports(current_task, previous_->masks[i],
+                                        previous_->ports[i],
+                                        previous_->behaviors[i],
+                                        previous_->flavors[i]);
+      if (result != KERN_SUCCESS)
+        return false;
+    }
+    
+    delete previous_;
+    previous_ = NULL;
+    installed_exception_handler_ = false;
+  }
+  
+  return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::Setup(bool install_handler) {
+  if (pthread_mutex_init(&minidump_write_mutex_, NULL))
+    return false;
+
+  // Create a receive right
+  mach_port_t current_task = mach_task_self();
+  kern_return_t result = mach_port_allocate(current_task,
+                                            MACH_PORT_RIGHT_RECEIVE,
+                                            &handler_port_);
+  // Add send right
+  if (result == KERN_SUCCESS)
+    result = mach_port_insert_right(current_task, handler_port_, handler_port_,
+                                    MACH_MSG_TYPE_MAKE_SEND);
+
+  if (install_handler && result == KERN_SUCCESS)
+    if (!InstallHandler())
+      return false;
+
+  if (result == KERN_SUCCESS) {
+    // Install the handler in its own thread, detached as we won't be joining.
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    int thread_create_result = pthread_create(&handler_thread_, &attr, 
+                                              &WaitForMessage, this);
+    pthread_attr_destroy(&attr);
+    result = thread_create_result ? KERN_FAILURE : KERN_SUCCESS;
+  }
+
+  return result == KERN_SUCCESS ? true : false;
+}
+
+bool ExceptionHandler::Teardown() {
+  kern_return_t result = KERN_SUCCESS;
+  is_in_teardown_ = true;
+
+  if (!UninstallHandler())
+    return false;
+  
+  // Send an empty message so that the handler_thread exits
+  if (SendEmptyMachMessage()) {
+    mach_port_t current_task = mach_task_self();
+    result = mach_port_deallocate(current_task, handler_port_);
+    if (result != KERN_SUCCESS)
+      return false;
+  } else {
+    return false;
+  }
+  
+  handler_thread_ = NULL;
+  handler_port_ = NULL;
+  pthread_mutex_destroy(&minidump_write_mutex_);
+
+  return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::SendEmptyMachMessage() {
+  ExceptionMessage empty;
+  memset(&empty, 0, sizeof(empty));
+  empty.header.msgh_size = sizeof(empty) - sizeof(empty.padding);
+  empty.header.msgh_remote_port = handler_port_;
+  empty.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
+                                          MACH_MSG_TYPE_MAKE_SEND_ONCE);
+  kern_return_t result = mach_msg(&(empty.header),
+                                  MACH_SEND_MSG | MACH_SEND_TIMEOUT,
+                                  empty.header.msgh_size, 0, 0,
+                                  MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+  return result == KERN_SUCCESS;
+}
+
+void ExceptionHandler::UpdateNextID() {
+  next_minidump_path_ =
+    (MinidumpGenerator::UniqueNameInDirectory(dump_path_, &next_minidump_id_));
+
+  next_minidump_path_c_ = next_minidump_path_.c_str();
+  next_minidump_id_c_ = next_minidump_id_.c_str();
+}
+
+bool ExceptionHandler::SuspendThreads() {
+  thread_act_port_array_t   threads_for_task;
+  mach_msg_type_number_t    thread_count;
+
+  if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+    return false;
+
+  // suspend all of the threads except for this one
+  for (unsigned int i = 0; i < thread_count; ++i) {
+    if (threads_for_task[i] != mach_thread_self()) {
+      if (thread_suspend(threads_for_task[i]))
+        return false;
+    }
+  }
+  
+  return true;
+}
+
+bool ExceptionHandler::ResumeThreads() {
+  thread_act_port_array_t   threads_for_task;
+  mach_msg_type_number_t    thread_count;
+
+  if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+    return false;
+
+  // resume all of the threads except for this one
+  for (unsigned int i = 0; i < thread_count; ++i) {
+    if (threads_for_task[i] != mach_thread_self()) {
+      if (thread_resume(threads_for_task[i]))
+        return false;
+    }
+  }
+  
+  return true;
+}
+
+}  // namespace google_breakpad
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.h
@@ -0,0 +1,193 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// exception_handler.h:  MacOS exception handler
+// This class can install a Mach exception port handler to trap most common
+// programming errors.  If an exception occurs, a minidump file will be
+// generated which contains detailed information about the process and the
+// exception.
+
+#ifndef CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
+#define CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
+
+#include <mach/mach.h>
+
+#include <string>
+
+namespace google_breakpad {
+
+using std::string;
+
+struct ExceptionParameters;
+
+class ExceptionHandler {
+ public:
+  // A callback function to run before Breakpad performs any substantial
+  // processing of an exception.  A FilterCallback is called before writing
+  // a minidump.  context is the parameter supplied by the user as
+  // callback_context when the handler was created.
+  //
+  // If a FilterCallback returns true, Breakpad will continue processing,
+  // 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);
+  
+  // A callback function to run after the minidump has been written.
+  // |minidump_id| is a unique id for the dump, so the minidump
+  // file is <dump_dir>/<minidump_id>.dmp.
+  // |context| is the value passed into the constructor. 
+  // |succeeded| indicates whether a minidump file was successfully written.
+  // Return true if the exception was fully handled and breakpad should exit.
+  // Return false to allow any other exception handlers to process the 
+  // exception.
+  typedef bool (*MinidumpCallback)(const char *dump_dir,
+                                   const char *minidump_id,
+                                   void *context, bool succeeded);
+
+  // Creates a new ExceptionHandler instance to handle writing minidumps.
+  // Minidump files will be written to dump_path, and the optional callback
+  // is called after writing the dump file, as described above.
+  // If install_handler is true, then a minidump will be written whenever
+  // an unhandled exception occurs.  If it is false, minidumps will only
+  // be written when WriteMinidump is called.
+  ExceptionHandler(const string &dump_path, 
+                   FilterCallback filter, MinidumpCallback callback,
+                   void *callback_context, bool install_handler);
+  ~ExceptionHandler();
+
+  // Get and set the minidump path.
+  string dump_path() const { return dump_path_; }
+  void set_dump_path(const string &dump_path) {
+    dump_path_ = dump_path;
+    dump_path_c_ = dump_path_.c_str();
+    UpdateNextID();  // Necessary to put dump_path_ in next_minidump_path_.
+  }
+  
+  // Writes a minidump immediately.  This can be used to capture the
+  // execution state independently of a crash.  Returns true on success.
+  bool WriteMinidump();
+
+  // Convenience form of WriteMinidump which does not require an
+  // ExceptionHandler instance.
+  static bool WriteMinidump(const string &dump_path, MinidumpCallback callback,
+                            void *callback_context);
+
+ private:
+  // Install the mach exception handler
+  bool InstallHandler();
+
+  // Uninstall the mach exception handler (if any)
+  bool UninstallHandler();
+      
+  // Setup the handler thread, and if |install_handler| is true, install the
+  // mach exception port handler
+  bool Setup(bool install_handler);
+    
+  // Uninstall the mach exception handler (if any) and terminate the helper
+  // thread
+  bool Teardown();
+
+  // Send an "empty" mach message to the exception handler.  Return true on
+  // success, false otherwise
+  bool SendEmptyMachMessage();
+
+  // All minidump writing goes through this one routine
+  bool WriteMinidumpWithException(int exception_type, int exception_code,
+                                  mach_port_t thread_name);
+
+  // When installed, this static function will be call from a newly created
+  // pthread with |this| as the argument
+  static void *WaitForMessage(void *exception_handler_class);
+
+  // disallow copy ctor and operator=
+  explicit ExceptionHandler(const ExceptionHandler &);
+  void operator=(const ExceptionHandler &);
+
+  // 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();
+
+  // These functions will suspend/resume all threads except for the 
+  // reporting thread
+  bool SuspendThreads();
+  bool ResumeThreads();
+  
+  // The destination directory for the minidump
+  string dump_path_;
+  
+  // The basename of the next minidump w/o extension
+  string next_minidump_id_;
+  
+  // The full path to the next minidump to be written, including extension
+  string next_minidump_path_;
+  
+  // Pointers to the UTF-8 versions of above
+  const char *dump_path_c_;
+  const char *next_minidump_id_c_;
+  const char *next_minidump_path_c_;
+
+  // The callback function and pointer to be passed back after the minidump
+  // has been written
+  FilterCallback filter_;
+  MinidumpCallback callback_;
+  void *callback_context_;
+
+  // The thread that is created for the handler
+  pthread_t handler_thread_;
+
+  // The port that is waiting on an exception message to be sent, if the
+  // handler is installed
+  mach_port_t handler_port_;
+
+  // These variables save the previous exception handler's data so that it
+  // can be re-installed when this handler is uninstalled
+  ExceptionParameters *previous_;
+
+  // True, if we've installed the exception handler
+  bool installed_exception_handler_;
+  
+  // True, if we're in the process of uninstalling the exception handler and
+  // the thread.
+  bool is_in_teardown_;
+  
+  // Save the last result of the last minidump
+  bool last_minidump_write_result_;
+  
+  // A mutex for use when writing out a minidump that was requested on a 
+  // thread other than the exception handler.
+  pthread_mutex_t minidump_write_mutex_;
+  
+  // True, if we're using the mutext to indicate when mindump writing occurs
+  bool use_minidump_write_mutex_;
+};
+
+}  // namespace google_breakpad
+
+#endif  // CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler_test.cc
@@ -0,0 +1,107 @@
+// 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.
+
+/*
+g++ -framework CoreFoundation -I../../.. \
+	../../minidump_file_writer.cc \
+	../../../common/convert_UTF.c \
+	../../../common/string_conversion.cc \
+	../../../common/mac/string_utilities.cc \
+	exception_handler.cc \
+	minidump_generator.cc \
+	exception_handler_test.cc \
+	-o exception_handler_test
+*/
+
+#include <pthread.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "exception_handler.h"
+#include "minidump_generator.h"
+
+using std::string;
+using google_breakpad::ExceptionHandler;
+
+static void *SleepyFunction(void *) {
+  while (1) {
+    sleep(10000);
+  }
+}
+
+static void Crasher() {
+  int *a = NULL;
+
+	fprintf(stdout, "Going to crash...\n");
+  fprintf(stdout, "A = %d", *a);
+}
+
+static void SoonToCrash() {
+  Crasher();
+}
+
+bool MDCallback(const char *dump_dir, const char *file_name,
+                void *context, bool success) {
+  string path(dump_dir);
+  string dest(dump_dir);
+  path.append(file_name);
+  path.append(".dmp");
+
+  fprintf(stdout, "Minidump: %s\n", path.c_str());
+  // Indicate that we've handled the callback
+  return true;
+}
+
+int main(int argc, char * const argv[]) {
+  char buffer[PATH_MAX];
+  struct passwd *user = getpwuid(getuid());
+
+  // Home dir
+  snprintf(buffer, sizeof(buffer), "/Users/%s/Desktop/", user->pw_name);
+
+  string path(buffer);
+  ExceptionHandler eh(path, NULL, MDCallback, NULL, true);
+  pthread_t t;
+
+  if (pthread_create(&t, NULL, SleepyFunction, NULL) == 0) {
+    pthread_detach(t);
+  } else {
+    perror("pthread_create");
+  }
+
+  // Dump a test
+  eh.WriteMinidump();
+
+	// Test the handler
+  SoonToCrash();
+
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc
@@ -0,0 +1,715 @@
+// 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.
+
+#include <cstdio>
+
+#include <mach/host_info.h>
+#include <mach/vm_statistics.h>
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <sys/sysctl.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "client/mac/handler/minidump_generator.h"
+#include "client/minidump_file_writer-inl.h"
+#include "common/mac/file_id.h"
+#include "common/mac/string_utilities.h"
+
+using MacStringUtils::ConvertToString;
+using MacStringUtils::IntegerValueAtIndex;
+
+namespace google_breakpad {
+  
+MinidumpGenerator::MinidumpGenerator()
+    : exception_type_(0),
+      exception_code_(0),
+      exception_thread_(0) {
+}
+
+MinidumpGenerator::~MinidumpGenerator() {
+}
+
+char MinidumpGenerator::build_string_[16];
+int MinidumpGenerator::os_major_version_ = 0;
+int MinidumpGenerator::os_minor_version_ = 0;
+int MinidumpGenerator::os_build_number_ = 0;
+
+// static
+void MinidumpGenerator::GatherSystemInformation() {
+  // 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);
+  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>
+    (CFDictionaryGetValue(list, CFSTR("ProductVersion")));
+  string build_str = ConvertToString(build_version);
+  string product_str = ConvertToString(product_version);
+
+  CFRelease(list);
+  CFRelease(sys_vers);
+  CFRelease(data);
+
+  strlcpy(build_string_, build_str.c_str(), sizeof(build_string_));
+
+  // Parse the string that looks like "10.4.8"
+  os_major_version_ = IntegerValueAtIndex(product_str, 0);
+  os_minor_version_ = IntegerValueAtIndex(product_str, 1);
+  os_build_number_ = IntegerValueAtIndex(product_str, 2);
+}
+
+string MinidumpGenerator::UniqueNameInDirectory(const string &dir,
+                                                string *unique_name) {
+  CFUUIDRef uuid = CFUUIDCreate(NULL);
+  CFStringRef uuid_cfstr = CFUUIDCreateString(NULL, uuid);
+  CFRelease(uuid);
+  string file_name(ConvertToString(uuid_cfstr));
+  CFRelease(uuid_cfstr);
+  string path(dir);
+
+  // Ensure that the directory (if non-empty) has a trailing slash so that
+  // we can append the file name and have a valid pathname.
+  if (!dir.empty()) {
+    if (dir.at(dir.size() - 1) != '/')
+      path.append(1, '/');
+  }
+
+  path.append(file_name);
+  path.append(".dmp");
+
+  if (unique_name)
+    *unique_name = file_name;
+
+  return path;
+}
+
+bool MinidumpGenerator::Write(const char *path) {
+  WriteStreamFN writers[] = {
+    &MinidumpGenerator::WriteThreadListStream,
+    &MinidumpGenerator::WriteSystemInfoStream,
+    &MinidumpGenerator::WriteModuleListStream,
+    &MinidumpGenerator::WriteMiscInfoStream,
+    &MinidumpGenerator::WriteBreakpadInfoStream,
+    // Exception stream needs to be the last entry in this array as it may
+    // be omitted in the case where the minidump is written without an
+    // exception.
+    &MinidumpGenerator::WriteExceptionStream,
+  };
+  bool result = true;
+
+  // If opening was successful, create the header, directory, and call each
+  // writer.  The destructor for the TypedMDRVAs will cause the data to be
+  // flushed.  The destructor for the MinidumpFileWriter will close the file.
+  if (writer_.Open(path)) {
+    TypedMDRVA<MDRawHeader> header(&writer_);
+    TypedMDRVA<MDRawDirectory> dir(&writer_);
+
+    if (!header.Allocate())
+      return false;
+
+    int writer_count = sizeof(writers) / sizeof(writers[0]);
+
+    // If we don't have exception information, don't write out the
+    // exception stream
+    if (!exception_thread_ && !exception_type_)
+      --writer_count;
+
+    // Add space for all writers
+    if (!dir.AllocateArray(writer_count))
+      return false;
+
+    MDRawHeader *header_ptr = header.get();
+    header_ptr->signature = MD_HEADER_SIGNATURE;
+    header_ptr->version = MD_HEADER_VERSION;
+    time(reinterpret_cast<time_t *>(&(header_ptr->time_date_stamp)));
+    header_ptr->stream_count = writer_count;
+    header_ptr->stream_directory_rva = dir.position();
+
+    MDRawDirectory local_dir;
+    for (int i = 0; (result) && (i < writer_count); ++i) {
+      result = (this->*writers[i])(&local_dir);
+
+      if (result)
+        dir.CopyIndex(i, &local_dir);
+    }
+  }
+
+  return result;
+}
+
+static size_t CalculateStackSize(vm_address_t start_addr) {
+  vm_address_t stack_region_base = start_addr;
+  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(mach_task_self(), &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
+
+    // include the original stack frame page (0xbffff000 - 0xc0000000)
+    stack_region_size += 0x1000;  
+  }
+
+  return result == KERN_SUCCESS ? 
+    stack_region_base + stack_region_size - start_addr : 0;
+}
+
+bool MinidumpGenerator::WriteStackFromStartAddress(
+    vm_address_t start_addr,
+    MDMemoryDescriptor *stack_location) {
+  UntypedMDRVA memory(&writer_);
+  size_t size = CalculateStackSize(start_addr);
+
+  // If there's an error in the calculation, return at least the current
+  // stack information
+  if (size == 0)
+    size = 16;
+
+  if (!memory.Allocate(size))
+    return false;
+
+  bool 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
+bool MinidumpGenerator::WriteStack(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;
+  return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+u_int64_t MinidumpGenerator::CurrentPCForStack(thread_state_data_t state) {
+  ppc_thread_state_t *machine_state =
+    reinterpret_cast<ppc_thread_state_t *>(state);
+
+  return machine_state->srr0;
+}
+
+bool MinidumpGenerator::WriteContext(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);
+
+  if (!context.Allocate())
+    return false;
+
+  *register_location = context.location();
+  MDRawContextPPC *context_ptr = context.get();
+  context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
+
+#define AddReg(a) context_ptr->a = machine_state->a
+#define AddGPR(a) context_ptr->gpr[a] = machine_state->r ## a
+  AddReg(srr0);
+  AddReg(cr);
+  AddReg(xer);
+  AddReg(ctr);
+  AddReg(mq);
+  AddReg(lr);
+  AddReg(vrsave);
+
+  AddGPR(0);
+  AddGPR(1);
+  AddGPR(2);
+  AddGPR(3);
+  AddGPR(4);
+  AddGPR(5);
+  AddGPR(6);
+  AddGPR(7);
+  AddGPR(8);
+  AddGPR(9);
+  AddGPR(10);
+  AddGPR(11);
+  AddGPR(12);
+  AddGPR(13);
+  AddGPR(14);
+  AddGPR(15);
+  AddGPR(16);
+  AddGPR(17);
+  AddGPR(18);
+  AddGPR(19);
+  AddGPR(20);
+  AddGPR(21);
+  AddGPR(22);
+  AddGPR(23);
+  AddGPR(24);
+  AddGPR(25);
+  AddGPR(26);
+  AddGPR(27);
+  AddGPR(28);
+  AddGPR(29);
+  AddGPR(30);
+  AddGPR(31);
+  return true;
+}
+
+#elif TARGET_CPU_X86
+bool MinidumpGenerator::WriteStack(thread_state_data_t state,
+                                   MDMemoryDescriptor *stack_location) {
+  x86_thread_state_t *machine_state =
+    reinterpret_cast<x86_thread_state_t *>(state);
+  vm_address_t start_addr = machine_state->uts.ts32.esp;
+  return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+u_int64_t MinidumpGenerator::CurrentPCForStack(thread_state_data_t state) {
+  x86_thread_state_t *machine_state =
+    reinterpret_cast<x86_thread_state_t *>(state);
+
+  return machine_state->uts.ts32.eip;
+}
+
+bool MinidumpGenerator::WriteContext(thread_state_data_t state,
+                                     MDLocationDescriptor *register_location) {
+  TypedMDRVA<MDRawContextX86> context(&writer_);
+  x86_thread_state_t *machine_state =
+    reinterpret_cast<x86_thread_state_t *>(state);
+
+  if (!context.Allocate())
+    return false;
+
+  *register_location = context.location();
+  MDRawContextX86 *context_ptr = context.get();
+  context_ptr->context_flags = MD_CONTEXT_X86;
+#define AddReg(a) context_ptr->a = machine_state->uts.ts32.a
+  AddReg(cs);
+  AddReg(ds);
+  AddReg(ss);
+  AddReg(es);
+  AddReg(fs);
+  AddReg(gs);
+  AddReg(eflags);
+
+  AddReg(eip);
+  AddReg(eax);
+  AddReg(ebx);
+  AddReg(ecx);
+  AddReg(edx);
+  AddReg(esi);
+  AddReg(edi);
+  AddReg(ebp);
+  AddReg(esp);
+  return true;
+}
+#endif
+
+bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
+                                          MDRawThread *thread) {
+  thread_state_data_t state;
+  mach_msg_type_number_t state_count = sizeof(state);
+
+  if (thread_get_state(thread_id, MACHINE_THREAD_STATE, state, &state_count) ==
+      KERN_SUCCESS) {
+    if (!WriteStack(state, &thread->stack))
+      return false;
+
+    if (!WriteContext(state, &thread->thread_context))
+      return false;
+
+    thread->thread_id = thread_id;
+  } else {
+    return false;
+  }
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteThreadListStream(
+    MDRawDirectory *thread_list_stream) {
+  TypedMDRVA<MDRawThreadList> list(&writer_);
+  thread_act_port_array_t threads_for_task;
+  mach_msg_type_number_t thread_count;
+  int non_generator_thread_count;
+
+  if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+    return false;
+
+  // Don't include the generator thread
+  non_generator_thread_count = thread_count - 1;
+  if (!list.AllocateObjectAndArray(non_generator_thread_count,
+                                   sizeof(MDRawThread)))
+    return false;
+
+  thread_list_stream->stream_type = MD_THREAD_LIST_STREAM;
+  thread_list_stream->location = list.location();
+
+  list.get()->number_of_threads = non_generator_thread_count;
+
+  MDRawThread thread;
+  int thread_idx = 0;
+
+  for (unsigned int i = 0; i < thread_count; ++i) {
+    memset(&thread, 0, sizeof(MDRawThread));
+
+    if (threads_for_task[i] != mach_thread_self()) {
+      if (!WriteThreadStream(threads_for_task[i], &thread))
+        return false;
+
+      list.CopyIndexAfterObject(thread_idx++, &thread, sizeof(MDRawThread));
+    }
+  }
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
+  TypedMDRVA<MDRawExceptionStream> exception(&writer_);
+
+  if (!exception.Allocate())
+    return false;
+
+  exception_stream->stream_type = MD_EXCEPTION_STREAM;
+  exception_stream->location = exception.location();
+  MDRawExceptionStream *exception_ptr = exception.get();
+  exception_ptr->thread_id = exception_thread_;
+
+  // This naming is confusing, but it is the proper translation from
+  // mach naming to minidump naming.
+  exception_ptr->exception_record.exception_code = exception_type_;
+  exception_ptr->exception_record.exception_flags = exception_code_;
+
+  thread_state_data_t state;
+  mach_msg_type_number_t stateCount = sizeof(state);
+
+  if (thread_get_state(exception_thread_, MACHINE_THREAD_STATE, state,
+                       &stateCount) != KERN_SUCCESS)
+    return false;
+
+  if (!WriteContext(state, &exception_ptr->thread_context))
+    return false;
+
+  exception_ptr->exception_record.exception_address = CurrentPCForStack(state);
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteSystemInfoStream(
+    MDRawDirectory *system_info_stream) {
+  TypedMDRVA<MDRawSystemInfo> info(&writer_);
+
+  if (!info.Allocate())
+    return false;
+
+  system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM;
+  system_info_stream->location = info.location();
+
+  // CPU Information
+  uint32_t cpu_type;
+  size_t len = sizeof(cpu_type);
+  sysctlbyname("hw.cputype", &cpu_type, &len, NULL, 0);
+  uint32_t number_of_processors;
+  len = sizeof(number_of_processors);
+  sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0);
+  MDRawSystemInfo *info_ptr = info.get();
+
+  switch (cpu_type) {
+    case CPU_TYPE_POWERPC:
+      info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC;
+      break;
+    case CPU_TYPE_I386:
+      info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86;
+      break;
+    default:
+      info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN;
+      break;
+  }
+
+  info_ptr->number_of_processors = number_of_processors;
+  info_ptr->platform_id = MD_OS_MAC_OS_X;
+
+  MDLocationDescriptor build_string_loc;
+
+  if (!writer_.WriteString(build_string_, 0,
+                           &build_string_loc))
+    return false;
+
+  info_ptr->csd_version_rva = build_string_loc.rva;
+  info_ptr->major_version = os_major_version_;
+  info_ptr->minor_version = os_minor_version_;
+  info_ptr->build_number = os_build_number_;
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteModuleStream(unsigned int index,
+                                          MDRawModule *module) {
+  const struct mach_header *header = _dyld_get_image_header(index);
+
+  if (!header)
+    return false;
+
+  int cpu_type = header->cputype;
+  unsigned long slide = _dyld_get_image_vmaddr_slide(index);
+  const char* name = _dyld_get_image_name(index);
+  const struct load_command *cmd =
+    reinterpret_cast<const struct load_command *>(header + 1);
+
+  memset(module, 0, sizeof(MDRawModule));
+
+  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);
+      if (!strcmp(seg->segname, "__TEXT")) {
+        MDLocationDescriptor string_location;
+
+        if (!writer_.WriteString(name, 0, &string_location))
+          return false;
+
+        module->base_of_image = seg->vmaddr + slide;
+        module->size_of_image = seg->vmsize;
+        module->module_name_rva = string_location.rva;
+
+        if (!WriteCVRecord(module, cpu_type, name))
+          return false;
+
+        return true;
+      }
+    }
+
+    cmd = reinterpret_cast<struct load_command *>((char *)cmd + cmd->cmdsize);
+  }
+
+  return true;
+}
+
+static int FindExecutableModule() {
+  int image_count = _dyld_image_count();
+  const struct mach_header *header;
+
+  for (int i = 0; i < image_count; ++i) {
+    header = _dyld_get_image_header(i);
+
+    if (header->filetype == MH_EXECUTE)
+      return i;
+  }
+
+  return 0;
+}
+
+bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type,
+                                      const char *module_path) {
+  TypedMDRVA<MDCVInfoPDB70> cv(&writer_);
+
+  // Only return the last path component of the full module path
+  char *module_name = strrchr(module_path, '/');
+
+  // Increment past the slash
+  if (module_name)
+    ++module_name;
+  else
+    module_name = "<Unknown>";
+
+  size_t module_name_length = strlen(module_name);
+
+  if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t)))
+    return false;
+
+  if (!cv.CopyIndexAfterObject(0, module_name, module_name_length))
+    return false;
+
+  module->cv_record = cv.location();
+  MDCVInfoPDB70 *cv_ptr = cv.get();
+  cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE;
+  cv_ptr->age = 0;
+
+  // 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 | 
+      (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];
+    cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7];
+    cv_ptr->signature.data4[0] = identifier[8];
+    cv_ptr->signature.data4[1] = identifier[9];
+    cv_ptr->signature.data4[2] = identifier[10];
+    cv_ptr->signature.data4[3] = identifier[11];
+    cv_ptr->signature.data4[4] = identifier[12];
+    cv_ptr->signature.data4[5] = identifier[13];
+    cv_ptr->signature.data4[6] = identifier[14];
+    cv_ptr->signature.data4[7] = identifier[15];
+  }
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteModuleListStream(
+    MDRawDirectory *module_list_stream) {
+  TypedMDRVA<MDRawModuleList> list(&writer_);
+
+  if (!_dyld_present())
+    return false;
+
+  int image_count = _dyld_image_count();
+
+  if (!list.AllocateObjectAndArray(image_count, MD_MODULE_SIZE))
+    return false;
+
+  module_list_stream->stream_type = MD_MODULE_LIST_STREAM;
+  module_list_stream->location = list.location();
+  list.get()->number_of_modules = image_count;
+
+  // Write out the executable module as the first one
+  MDRawModule module;
+  int executableIndex = FindExecutableModule();
+
+  if (!WriteModuleStream(executableIndex, &module))
+    return false;
+
+  list.CopyIndexAfterObject(0, &module, MD_MODULE_SIZE);
+  int destinationIndex = 1;  // Write all other modules after this one
+
+  for (int i = 0; i < image_count; ++i) {
+    if (i != executableIndex) {
+      if (!WriteModuleStream(i, &module))
+        return false;
+
+      list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE);
+    }
+  }
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *misc_info_stream) {
+  TypedMDRVA<MDRawMiscInfo> info(&writer_);
+
+  if (!info.Allocate())
+    return false;
+
+  misc_info_stream->stream_type = MD_MISC_INFO_STREAM;
+  misc_info_stream->location = info.location();
+
+  MDRawMiscInfo *info_ptr = info.get();
+  info_ptr->size_of_info = sizeof(MDRawMiscInfo);
+  info_ptr->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID |
+    MD_MISCINFO_FLAGS1_PROCESS_TIMES |
+    MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO;
+
+  // Process ID
+  info_ptr->process_id = getpid();
+
+  // Times
+  struct rusage usage;
+  if (getrusage(RUSAGE_SELF, &usage) != -1) {
+    // Omit the fractional time since the MDRawMiscInfo only wants seconds
+    info_ptr->process_user_time = usage.ru_utime.tv_sec;
+    info_ptr->process_kernel_time = usage.ru_stime.tv_sec;
+  }
+  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) {
+      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);
+    }
+  }
+
+  // Speed
+  uint64_t speed;
+  size = sizeof(speed);
+  sysctlbyname("hw.cpufrequency_max", &speed, &size, NULL, 0);
+  info_ptr->processor_max_mhz = speed / (1000 * 1000);
+  info_ptr->processor_mhz_limit = speed / (1000 * 1000);
+  size = sizeof(speed);
+  sysctlbyname("hw.cpufrequency", &speed, &size, NULL, 0);
+  info_ptr->processor_current_mhz = speed / (1000 * 1000);
+
+  return true;
+}
+
+bool MinidumpGenerator::WriteBreakpadInfoStream(
+    MDRawDirectory *breakpad_info_stream) {
+  TypedMDRVA<MDRawBreakpadInfo> info(&writer_);
+
+  if (!info.Allocate())
+    return false;
+
+  breakpad_info_stream->stream_type = MD_BREAKPAD_INFO_STREAM;
+  breakpad_info_stream->location = info.location();
+  MDRawBreakpadInfo *info_ptr = info.get();
+
+  if (exception_thread_ && exception_type_) {
+    info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
+                         MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
+    info_ptr->dump_thread_id = mach_thread_self();
+    info_ptr->requesting_thread_id = exception_thread_;
+  } else {
+    info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID;
+    info_ptr->dump_thread_id = mach_thread_self();
+    info_ptr->requesting_thread_id = 0;
+  }
+
+  return true;
+}
+
+}  // namespace google_breakpad
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h
@@ -0,0 +1,123 @@
+// 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_generator.h:  Create a minidump of the current MacOS process.
+
+#ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
+#define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
+
+#include <mach/mach.h>
+
+#include <string>
+
+#include "client/minidump_file_writer.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+using std::string;
+
+// 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.
+// Usage:
+// MinidumpGenerator minidump();
+// minidump.Write("/tmp/minidump");
+//
+class MinidumpGenerator {
+ public:
+  MinidumpGenerator();
+  ~MinidumpGenerator();
+
+  // Return <dir>/<unique_name>.dmp
+  // Sets |unique_name| (if requested) to the unique name for the minidump
+  static string UniqueNameInDirectory(const string &dir, string *unique_name);
+
+  // Write out the minidump into |path|
+  // All of the components of |path| must exist and be writable
+  // Return true if successful, false otherwise
+  bool Write(const char *path);
+
+  // Specify some exception information, if applicable
+  void SetExceptionInformation(int type, int code, mach_port_t thread_name) {
+    exception_type_ = type;
+    exception_code_ = code;
+    exception_thread_ = thread_name;
+  }
+
+  // Gather system information.  This should be call at least once before using
+  // the MinidumpGenerator class.
+  static void GatherSystemInformation();
+
+ private:
+    typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *);
+
+  // Stream writers
+  bool WriteThreadListStream(MDRawDirectory *thread_list_stream);
+  bool WriteExceptionStream(MDRawDirectory *exception_stream);
+  bool WriteSystemInfoStream(MDRawDirectory *system_info_stream);
+  bool WriteModuleListStream(MDRawDirectory *module_list_stream);
+  bool WriteMiscInfoStream(MDRawDirectory *misc_info_stream);
+  bool WriteBreakpadInfoStream(MDRawDirectory *breakpad_info_stream);
+
+  // Helpers
+  u_int64_t CurrentPCForStack(thread_state_data_t state);
+  bool WriteStackFromStartAddress(vm_address_t start_addr,
+                                  MDMemoryDescriptor *stack_location);
+  bool WriteStack(thread_state_data_t state,
+                  MDMemoryDescriptor *stack_location);
+  bool WriteContext(thread_state_data_t state,
+                    MDLocationDescriptor *register_location);
+  bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
+  bool WriteCVRecord(MDRawModule *module, int cpu_type, 
+                     const char *module_path);
+  bool WriteModuleStream(unsigned int index, MDRawModule *module);
+
+  // disallow copy ctor and operator=
+  explicit MinidumpGenerator(const MinidumpGenerator &);
+  void operator=(const MinidumpGenerator &);
+
+  // Use this writer to put the data to disk
+  MinidumpFileWriter writer_;
+
+  // Exception information
+  int exception_type_;
+  int exception_code_;
+  mach_port_t exception_thread_;
+
+  // System information
+  static char build_string_[16];
+  static int os_major_version_;
+  static int os_minor_version_;
+  static int os_build_number_;
+};
+
+}  // namespace google_breakpad
+
+#endif  // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc
@@ -0,0 +1,78 @@
+// 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.
+
+#include <unistd.h>
+
+#include <pthread.h>
+#include <pwd.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "minidump_generator.h"
+#include "minidump_file_writer.h"
+
+using std::string;
+using google_breakpad::MinidumpGenerator;
+
+static bool doneWritingReport = false;
+
+static void *Reporter(void *) {
+  char buffer[PATH_MAX];
+  MinidumpGenerator md;
+  struct passwd *user = getpwuid(getuid());
+
+  // Write it to the desktop
+  snprintf(buffer, sizeof(buffer), "/Users/%s/Desktop/test.dmp", user->pw_name);
+  fprintf(stdout, "Writing %s\n", buffer);
+
+  md.Write(buffer);
+  doneWritingReport = true;
+
+  return NULL;
+}
+
+static void SleepyFunction() {
+  while (!doneWritingReport) {
+    usleep(100);
+  }
+}
+
+int main(int argc, char * const argv[]) {
+  pthread_t reporter_thread;
+
+  if (pthread_create(&reporter_thread, NULL, Reporter, NULL) == 0) {
+    pthread_detach(reporter_thread);
+  } else {
+    perror("pthread_create");
+  }
+
+  SleepyFunction();
+
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj
@@ -0,0 +1,447 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		9B35FF5A0B267D5F008DE8C7 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.c */; };
+		9B35FF5B0B267D5F008DE8C7 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+		9B37CEEC0AF98ECD00FA4BD4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */; };
+		9B7CA7700B12873A00CD3A1D /* minidump_file_writer-inl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */; };
+		9B7CA8540B12989000CD3A1D /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */; };
+		9B7CA8550B1298A100CD3A1D /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+		9BC1D2940B336F2300F2A2B4 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.c */; };
+		9BC1D2950B336F2500F2A2B4 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+		9BD82AC10B0029DF0055103E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */; };
+		9BD82BFF0B01333D0055103E /* exception_handler_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */; };
+		9BD82C020B01333D0055103E /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */; };
+		9BD82C0D0B0133520055103E /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C090B0133520055103E /* exception_handler.cc */; };
+		9BD82C0E0B0133520055103E /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C0B0B0133520055103E /* minidump_generator.cc */; };
+		9BD82C0F0B0133520055103E /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C090B0133520055103E /* exception_handler.cc */; };
+		9BD82C100B0133520055103E /* exception_handler.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C0A0B0133520055103E /* exception_handler.h */; };
+		9BD82C110B0133520055103E /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C0B0B0133520055103E /* minidump_generator.cc */; };
+		9BD82C120B0133520055103E /* minidump_generator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C0C0B0133520055103E /* minidump_generator.h */; };
+		9BD82C250B01344C0055103E /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+		9BD82C260B01344C0055103E /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+		9BD82C270B01344C0055103E /* minidump_file_writer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C240B01344C0055103E /* minidump_file_writer.h */; };
+		9BD82C2D0B01345E0055103E /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C2B0B01345E0055103E /* string_utilities.cc */; };
+		9BD82C2E0B01345E0055103E /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C2B0B01345E0055103E /* string_utilities.cc */; };
+		9BD82C2F0B01345E0055103E /* string_utilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C2C0B01345E0055103E /* string_utilities.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		8DD76F690486A84900D96B5E /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+				9BD82C100B0133520055103E /* exception_handler.h in CopyFiles */,
+				9BD82C120B0133520055103E /* minidump_generator.h in CopyFiles */,
+				9BD82C270B01344C0055103E /* minidump_file_writer.h in CopyFiles */,
+				9BD82C2F0B01345E0055103E /* string_utilities.h in CopyFiles */,
+				9B7CA7700B12873A00CD3A1D /* minidump_file_writer-inl.h in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		8DD76F6C0486A84900D96B5E /* generator_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generator_test; sourceTree = BUILT_PRODUCTS_DIR; };
+		9B35FF560B267D5F008DE8C7 /* convert_UTF.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = convert_UTF.c; path = ../../../common/convert_UTF.c; sourceTree = SOURCE_ROOT; };
+		9B35FF570B267D5F008DE8C7 /* convert_UTF.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = convert_UTF.h; path = ../../../common/convert_UTF.h; sourceTree = SOURCE_ROOT; };
+		9B35FF580B267D5F008DE8C7 /* string_conversion.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string_conversion.cc; path = ../../../common/string_conversion.cc; sourceTree = SOURCE_ROOT; };
+		9B35FF590B267D5F008DE8C7 /* string_conversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = string_conversion.h; path = ../../../common/string_conversion.h; sourceTree = SOURCE_ROOT; };
+		9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+		9B7CA84E0B1297F200CD3A1D /* unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unit_test; sourceTree = BUILT_PRODUCTS_DIR; };
+		9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer_unittest.cc; path = ../../minidump_file_writer_unittest.cc; sourceTree = "<group>"; };
+		9BD82A9B0B00267E0055103E /* handler_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = handler_test; sourceTree = BUILT_PRODUCTS_DIR; };
+		9BD82BFD0B01333D0055103E /* exception_handler_test.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = exception_handler_test.cc; sourceTree = SOURCE_ROOT; };
+		9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = minidump_generator_test.cc; sourceTree = SOURCE_ROOT; };
+		9BD82C090B0133520055103E /* exception_handler.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = exception_handler.cc; sourceTree = SOURCE_ROOT; };
+		9BD82C0A0B0133520055103E /* exception_handler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = exception_handler.h; sourceTree = SOURCE_ROOT; };
+		9BD82C0B0B0133520055103E /* minidump_generator.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = minidump_generator.cc; sourceTree = SOURCE_ROOT; };
+		9BD82C0C0B0133520055103E /* minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_generator.h; sourceTree = SOURCE_ROOT; };
+		9BD82C230B01344C0055103E /* minidump_file_writer.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer.cc; path = ../../minidump_file_writer.cc; sourceTree = SOURCE_ROOT; };
+		9BD82C240B01344C0055103E /* minidump_file_writer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = minidump_file_writer.h; path = ../../minidump_file_writer.h; sourceTree = SOURCE_ROOT; };
+		9BD82C2B0B01345E0055103E /* string_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string_utilities.cc; path = ../../../common/mac/string_utilities.cc; sourceTree = SOURCE_ROOT; };
+		9BD82C2C0B01345E0055103E /* string_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = string_utilities.h; path = ../../../common/mac/string_utilities.h; sourceTree = SOURCE_ROOT; };
+		9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "minidump_file_writer-inl.h"; path = "../../minidump_file_writer-inl.h"; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		8DD76F660486A84900D96B5E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9B37CEEC0AF98ECD00FA4BD4 /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9B7CA84C0B1297F200CD3A1D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9BD82A990B00267E0055103E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9BD82AC10B0029DF0055103E /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		08FB7794FE84155DC02AAC07 /* MinidumpWriter */ = {
+			isa = PBXGroup;
+			children = (
+				9BD82C040B0133420055103E /* Breakpad */,
+				08FB7795FE84155DC02AAC07 /* Source */,
+				9B37CEEA0AF98EB600FA4BD4 /* Frameworks */,
+				1AB674ADFE9D54B511CA2CBB /* Products */,
+			);
+			name = MinidumpWriter;
+			sourceTree = "<group>";
+		};
+		08FB7795FE84155DC02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				9BD82BFD0B01333D0055103E /* exception_handler_test.cc */,
+				9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */,
+				9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		1AB674ADFE9D54B511CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8DD76F6C0486A84900D96B5E /* generator_test */,
+				9BD82A9B0B00267E0055103E /* handler_test */,
+				9B7CA84E0B1297F200CD3A1D /* unit_test */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		9B37CEEA0AF98EB600FA4BD4 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		9BD82C040B0133420055103E /* Breakpad */ = {
+			isa = PBXGroup;
+			children = (
+				9B35FF560B267D5F008DE8C7 /* convert_UTF.c */,
+				9B35FF570B267D5F008DE8C7 /* convert_UTF.h */,
+				9B35FF580B267D5F008DE8C7 /* string_conversion.cc */,
+				9B35FF590B267D5F008DE8C7 /* string_conversion.h */,
+				9BD82C090B0133520055103E /* exception_handler.cc */,
+				9BD82C0A0B0133520055103E /* exception_handler.h */,
+				9BD82C0B0B0133520055103E /* minidump_generator.cc */,
+				9BD82C0C0B0133520055103E /* minidump_generator.h */,
+				9BD82C230B01344C0055103E /* minidump_file_writer.cc */,
+				9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */,
+				9BD82C240B01344C0055103E /* minidump_file_writer.h */,
+				9BD82C2B0B01345E0055103E /* string_utilities.cc */,
+				9BD82C2C0B01345E0055103E /* string_utilities.h */,
+			);
+			name = Breakpad;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		8DD76F620486A84900D96B5E /* generator_test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "generator_test" */;
+			buildPhases = (
+				8DD76F640486A84900D96B5E /* Sources */,
+				8DD76F660486A84900D96B5E /* Frameworks */,
+				8DD76F690486A84900D96B5E /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = generator_test;
+			productInstallPath = "$(HOME)/bin";
+			productName = MinidumpWriter;
+			productReference = 8DD76F6C0486A84900D96B5E /* generator_test */;
+			productType = "com.apple.product-type.tool";
+		};
+		9B7CA84D0B1297F200CD3A1D /* unit_test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 9B7CA8500B12984300CD3A1D /* Build configuration list for PBXNativeTarget "unit_test" */;
+			buildPhases = (
+				9B7CA84B0B1297F200CD3A1D /* Sources */,
+				9B7CA84C0B1297F200CD3A1D /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = unit_test;
+			productName = "filewriter unit test";
+			productReference = 9B7CA84E0B1297F200CD3A1D /* unit_test */;
+			productType = "com.apple.product-type.tool";
+		};
+		9BD82A9A0B00267E0055103E /* handler_test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 9BD82AA60B0026BF0055103E /* Build configuration list for PBXNativeTarget "handler_test" */;
+			buildPhases = (
+				9BD82A980B00267E0055103E /* Sources */,
+				9BD82A990B00267E0055103E /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = handler_test;
+			productName = ExceptionTester;
+			productReference = 9BD82A9B0B00267E0055103E /* handler_test */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		08FB7793FE84155DC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */;
+			hasScannedForEncodings = 1;
+			mainGroup = 08FB7794FE84155DC02AAC07 /* MinidumpWriter */;
+			projectDirPath = "";
+			targets = (
+				8DD76F620486A84900D96B5E /* generator_test */,
+				9BD82A9A0B00267E0055103E /* handler_test */,
+				9B7CA84D0B1297F200CD3A1D /* unit_test */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		8DD76F640486A84900D96B5E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9BD82C020B01333D0055103E /* minidump_generator_test.cc in Sources */,
+				9BD82C0F0B0133520055103E /* exception_handler.cc in Sources */,
+				9BD82C110B0133520055103E /* minidump_generator.cc in Sources */,
+				9BD82C260B01344C0055103E /* minidump_file_writer.cc in Sources */,
+				9BD82C2E0B01345E0055103E /* string_utilities.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9B7CA84B0B1297F200CD3A1D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9B7CA8540B12989000CD3A1D /* minidump_file_writer_unittest.cc in Sources */,
+				9B7CA8550B1298A100CD3A1D /* minidump_file_writer.cc in Sources */,
+				9BC1D2940B336F2300F2A2B4 /* convert_UTF.c in Sources */,
+				9BC1D2950B336F2500F2A2B4 /* string_conversion.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9BD82A980B00267E0055103E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9BD82BFF0B01333D0055103E /* exception_handler_test.cc in Sources */,
+				9BD82C0D0B0133520055103E /* exception_handler.cc in Sources */,
+				9BD82C0E0B0133520055103E /* minidump_generator.cc in Sources */,
+				9BD82C250B01344C0055103E /* minidump_file_writer.cc in Sources */,
+				9BD82C2D0B01345E0055103E /* string_utilities.cc in Sources */,
+				9B35FF5A0B267D5F008DE8C7 /* convert_UTF.c in Sources */,
+				9B35FF5B0B267D5F008DE8C7 /* string_conversion.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB923208733DC60010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_CW_ASM_SYNTAX = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_ENABLE_PASCAL_STRINGS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_THREADSAFE_STATICS = NO;
+				INSTALL_PATH = "$(HOME)/bin";
+				PRODUCT_NAME = generator_test;
+				USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+				ZERO_LINK = NO;
+			};
+			name = Debug;
+		};
+		1DEB923308733DC60010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					ppc,
+					i386,
+				);
+				GCC_CW_ASM_SYNTAX = NO;
+				GCC_ENABLE_PASCAL_STRINGS = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_THREADSAFE_STATICS = NO;
+				INSTALL_PATH = "$(HOME)/bin";
+				PRODUCT_NAME = generator_test;
+				USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		1DEB923608733DC60010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = Debug;
+		};
+		1DEB923708733DC60010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = Release;
+		};
+		9B7CA8510B12984300CD3A1D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = unit_test;
+				USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+				ZERO_LINK = NO;
+			};
+			name = Debug;
+		};
+		9B7CA8520B12984300CD3A1D /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = "$(HOME)/bin";
+				PREBINDING = NO;
+				PRODUCT_NAME = unit_test;
+				USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		9BD82AA70B0026BF0055103E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					"$(NATIVE_ARCH)",
+					i386,
+				);
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				INSTALL_PATH = "$(HOME)/bin";
+				OTHER_CFLAGS = "-Wall";
+				PREBINDING = NO;
+				PRODUCT_NAME = handler_test;
+				USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)";
+				ZERO_LINK = NO;
+			};
+			name = Debug;
+		};
+		9BD82AA80B0026BF0055103E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					"$(NATIVE_ARCH)",
+					i386,
+				);
+				COPY_PHASE_STRIP = YES;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				INSTALL_PATH = "$(HOME)/bin";
+				OTHER_CFLAGS = "-Wall";
+				PREBINDING = NO;
+				PRODUCT_NAME = handler_test;
+				USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)";
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "generator_test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB923208733DC60010E9CD /* Debug */,
+				1DEB923308733DC60010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB923608733DC60010E9CD /* Debug */,
+				1DEB923708733DC60010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		9B7CA8500B12984300CD3A1D /* Build configuration list for PBXNativeTarget "unit_test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9B7CA8510B12984300CD3A1D /* Debug */,
+				9B7CA8520B12984300CD3A1D /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		9BD82AA60B0026BF0055103E /* Build configuration list for PBXNativeTarget "handler_test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9BD82AA70B0026BF0055103E /* Debug */,
+				9BD82AA80B0026BF0055103E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
--- a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer-inl.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer-inl.h
@@ -33,17 +33,17 @@
 
 #ifndef CLIENT_MINIDUMP_FILE_WRITER_INL_H__
 #define CLIENT_MINIDUMP_FILE_WRITER_INL_H__
 
 #include <assert.h>
 
 #include "client/minidump_file_writer.h"
 
-namespace google_airbag {
+namespace google_breakpad {
 
 template<typename MDType>
 inline bool TypedMDRVA<MDType>::Allocate() {
   allocation_state_ = SINGLE_OBJECT;
   return UntypedMDRVA::Allocate(sizeof(MDType));
 }
 
 template<typename MDType>
@@ -81,11 +81,11 @@ inline bool TypedMDRVA<MDType>::CopyInde
   return writer_->Copy(position_ + sizeof(MDType) + index * size, src, size);
 }
 
 template<typename MDType>
 inline bool TypedMDRVA<MDType>::Flush() {
   return writer_->Copy(position_, &data_, sizeof(MDType));
 }
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
 
 #endif  // CLIENT_MINIDUMP_FILE_WRITER_INL_H__
--- a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc
@@ -33,194 +33,196 @@
 
 #include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "client/minidump_file_writer-inl.h"
+#include "common/string_conversion.h"
 
-namespace google_airbag {
+namespace google_breakpad {
+
+const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1);
 
 MinidumpFileWriter::MinidumpFileWriter() : file_(-1), position_(0), size_(0) {
 }
 
 MinidumpFileWriter::~MinidumpFileWriter() {
   Close();
 }
 
-bool MinidumpFileWriter::Open(const std::string &path) {
+bool MinidumpFileWriter::Open(const char *path) {
   assert(file_ == -1);
-  file_ = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+  file_ = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 
   return file_ != -1;
 }
 
 bool MinidumpFileWriter::Close() {
   bool result = true;
 
   if (file_ != -1) {
     ftruncate(file_, position_);
-    result = close(file_) == 0;
+    result = (close(file_) == 0);
     file_ = -1;
   }
 
   return result;
 }
 
-bool MinidumpFileWriter::WriteString(const wchar_t *str,
-                                     unsigned int length,
-                                     MDLocationDescriptor *location) {
+bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
+                                              unsigned int length,
+                                              TypedMDRVA<MDString> *mdstring) {
+  bool result = true;
+  if (sizeof(wchar_t) == sizeof(u_int16_t)) {
+    // Shortcut if wchar_t is the same size as MDString's buffer
+    result = mdstring->Copy(str, mdstring->get()->length);
+  } else {
+    u_int16_t out[2];
+    int out_idx = 0;
+    
+    // Copy the string character by character
+    while (length && result) {
+      UTF32ToUTF16Char(*str, out);
+      if (!out[0])
+        return false;
+      
+      // Process one character at a time
+      --length;
+      ++str;
+      
+      // Append the one or two UTF-16 characters.  The first one will be non-
+      // zero, but the second one may be zero, depending on the conversion from
+      // UTF-32.
+      int out_count = out[1] ? 2 : 1;
+      int out_size = sizeof(u_int16_t) * out_count;
+      result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
+      out_idx += out_count;
+    }
+  }
+  return result;
+}
+
+bool MinidumpFileWriter::CopyStringToMDString(const char *str,
+                                              unsigned int length,
+                                              TypedMDRVA<MDString> *mdstring) {
+  bool result = true;
+  u_int16_t out[2];
+  int out_idx = 0;
+
+  // Copy the string character by character
+  while (length && result) {
+    int conversion_count = UTF8ToUTF16Char(str, length, out);
+    if (!conversion_count)
+      return false;
+    
+    // Move the pointer along based on the nubmer of converted characters
+    length -= conversion_count;
+    str += conversion_count;
+    
+    // Append the one or two UTF-16 characters
+    int out_count = out[1] ? 2 : 1;
+    int out_size = sizeof(u_int16_t) * out_count;
+    result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
+    out_idx += out_count;
+  }
+  return result;
+}
+
+template <typename CharType>
+bool MinidumpFileWriter::WriteStringCore(const CharType *str,
+                                         unsigned int length,
+                                         MDLocationDescriptor *location) {
   assert(str);
   assert(location);
   // Calculate the mdstring length by either limiting to |length| as passed in
   // or by finding the location of the NULL character.
+  unsigned int mdstring_length = 0;
   if (!length)
     length = INT_MAX;
-
-  unsigned int mdstring_length = 0;
-  for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length) {
-  }
+  for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length)
+    ;
 
   // Allocate the string buffer
   TypedMDRVA<MDString> mdstring(this);
-
   if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(u_int16_t)))
     return false;
 
-  // Set length excluding the NULL
+  // Set length excluding the NULL and copy the string
   mdstring.get()->length = mdstring_length * sizeof(u_int16_t);
-
-  u_int16_t ch;
-  bool result = true;
-
-  if (sizeof(wchar_t) == sizeof(u_int16_t)) {
-    // Shortcut if wchar_t is the same size as MDString's buffer
-    result = mdstring.Copy(str, mdstring.get()->length);
-  } else {
-    // Copy the string character by character
-    for (unsigned int c = 0; c < mdstring_length && result == true; c++) {
-      ch = str[c];
-      // TODO: For the UTF-32->UTF-16 conversion, it's possible that there
-      // are characters that will require more than one UTF-16 character to
-      // represent it.  Fully supporting this will require a more sophisticated
-      // calculation of the size of the resulting string and for converting the
-      // UTF-32 character into the two UTF-16 characters.
-      result = mdstring.CopyIndexAfterObject(c, &ch, sizeof(ch));
-    }
-  }
+  bool result = CopyStringToMDString(str, mdstring_length, &mdstring);
 
   // NULL terminate
   if (result) {
-    ch = 0;
+    u_int16_t ch = 0;
     result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch));
 
     if (result)
       *location = mdstring.location();
   }
 
   return result;
 }
 
-bool MinidumpFileWriter::WriteString(const char *str, unsigned int length,
-                                     MDLocationDescriptor *location) {
-  assert(str);
-  assert(location);
-  // Calculate the mdstring length by either limiting to |length| as passed in
-  // or by finding the location of the NULL character.
-  if (!length)
-    length = INT_MAX;
-
-  unsigned int mdstring_length = 0;
-  for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length) {
-  }
-
-  // Allocate the string buffer
-  TypedMDRVA<MDString> mdstring(this);
-
-  if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(u_int16_t)))
-    return false;
-
-  // Set length excluding the NULL
-  mdstring.get()->length = mdstring_length * sizeof(u_int16_t);
+bool MinidumpFileWriter::WriteString(const wchar_t *str, unsigned int length,
+                 MDLocationDescriptor *location) {
+  return WriteStringCore(str, length, location);
+}
 
-  u_int16_t ch;
-  bool result = true;
-
-  // Copy the string character by character
-  for (unsigned int c = 0; c < mdstring_length && result == true; c++) {
-    ch = str[c];
-    // TODO: For the UTF-8->UTF-16 conversion, it's possible that there are
-    // characters that will convert one or more UTF-8 character into a single
-    // UTF-16 character.  Fully supporting this will require a more
-    // sophisticated calculation of the size of the resulting string and for
-    // converting the UTF-8 characters into a UTF-16 character.
-    result = mdstring.CopyIndexAfterObject(c, &ch, sizeof(ch));
-  }
-
-  // NULL terminate
-  if (result) {
-    ch = 0;
-    result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch));
-
-    if (result)
-      *location = mdstring.location();
-  }
-
-  return result;
+bool MinidumpFileWriter::WriteString(const char *str, unsigned int length,
+                 MDLocationDescriptor *location) {
+  return WriteStringCore(str, length, location);
 }
 
 bool MinidumpFileWriter::WriteMemory(const void *src, size_t size,
                                      MDMemoryDescriptor *output) {
   assert(src);
   assert(output);
   UntypedMDRVA mem(this);
 
   if (!mem.Allocate(size))
     return false;
-
   if (!mem.Copy(src, mem.size()))
     return false;
 
   output->start_of_memory_range = reinterpret_cast<u_int64_t>(src);
   output->memory = mem.location();
 
   return true;
 }
 
 MDRVA MinidumpFileWriter::Allocate(size_t size) {
   assert(size);
   assert(file_ != -1);
-
   size_t aligned_size = (size + 7) & ~7;  // 64-bit alignment
 
   if (position_ + aligned_size > size_) {
     size_t growth = aligned_size;
     size_t minimal_growth = getpagesize();
 
     // Ensure that the file grows by at least the size of a memory page
     if (growth < minimal_growth)
       growth = minimal_growth;
 
     size_t new_size = size_ + growth;
-
     if (ftruncate(file_, new_size) != 0)
       return kInvalidMDRVA;
 
     size_ = new_size;
   }
 
   MDRVA current_position = position_;
   position_ += static_cast<MDRVA>(aligned_size);
 
   return current_position;
 }
 
-bool MinidumpFileWriter::Copy(MDRVA position, const void* src, ssize_t size) {
+bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
   assert(src);
   assert(size);
   assert(file_ != -1);
 
   // Ensure that the data will fit in the allocated space
   if (size + position > size_)
     return false;
 
@@ -241,9 +243,9 @@ bool UntypedMDRVA::Allocate(size_t size)
 
 bool UntypedMDRVA::Copy(MDRVA position, const void *src, size_t size) {
   assert(src);
   assert(size);
   assert(position + size <= position_ + size_);
   return writer_->Copy(position, src, size);
 }
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
--- a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.h
@@ -22,69 +22,86 @@
 // 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_file_writer.h:  Implements file-based minidump generation
+// minidump_file_writer.h:  Implements file-based minidump generation.  It's
+// intended to be used with the Google Breakpad open source crash handling
+// project.
 
 #ifndef CLIENT_MINIDUMP_FILE_WRITER_H__
 #define CLIENT_MINIDUMP_FILE_WRITER_H__
 
 #include <string>
 
-#include "google_airbag/common/minidump_format.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+class UntypedMDRVA;
+template<typename MDType> class TypedMDRVA;
 
-namespace google_airbag {
-
+// The user of this class can Open() a file and add minidump streams, data, and
+// strings using the definitions in minidump_format.h.  Since this class is
+// expected to be used in a situation where the current process may be
+// damaged, it will not allocate heap memory.
+// Sample usage:
+// MinidumpFileWriter writer;
+// writer.Open("/tmp/minidump.dmp");
+// TypedMDRVA<MDRawHeader> header(&writer_);
+// header.Allocate();
+// header->get()->signature = MD_HEADER_SIGNATURE;
+//  :
+// writer.Close();
 class MinidumpFileWriter {
- public:
+public:
   // Invalid MDRVA (Minidump Relative Virtual Address)
   // returned on failed allocation
-  static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1);
+  static const MDRVA kInvalidMDRVA;
 
   MinidumpFileWriter();
   ~MinidumpFileWriter();
 
   // Open |path| as the destination of the minidump data.  Any existing file
   // will be overwritten.
   // Return true on success, or false on failure
-  bool Open(const std::string &path);
+  bool Open(const char *path);
 
   // Close the current file
   // Return true on success, or false on failure
   bool Close();
 
-  // Write |str| to a MDString.
+  // Copy the contents of |str| to a MDString and write it to the file.
   // |str| is expected to be either UTF-16 or UTF-32 depending on the size
   // of wchar_t.
   // Maximum |length| of characters to copy from |str|, or specify 0 to use the
   // entire NULL terminated string.  Copying will stop at the first NULL.
   // |location| the allocated location
   // Return true on success, or false on failure
   bool WriteString(const wchar_t *str, unsigned int length,
                    MDLocationDescriptor *location);
 
-  // Similar to above with |str| as an UTF-8 encoded string
+  // Same as above, except with |str| as a UTF-8 string
   bool WriteString(const char *str, unsigned int length,
                    MDLocationDescriptor *location);
 
   // Write |size| bytes starting at |src| into the current position.
   // Return true on success and set |output| to position, or false on failure
   bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output);
 
   // Copies |size| bytes from |src| to |position|
   // Return true on success, or false on failure
   bool Copy(MDRVA position, const void *src, ssize_t size);
 
   // Return the current position for writing to the minidump
-  MDRVA position() const { return position_; }
+  inline MDRVA position() const { return position_; }
 
  private:
   friend class UntypedMDRVA;
 
   // Allocates an area of |size| bytes.
   // Returns the position of the allocation, or kInvalidMDRVA if it was
   // unable to allocate the bytes.
   MDRVA Allocate(size_t size);
@@ -92,48 +109,63 @@ class MinidumpFileWriter {
   // The file descriptor for the output file
   int file_;
 
   // Current position in buffer
   MDRVA position_;
 
   // Current allocated size
   size_t size_;
+
+  // Copy |length| characters from |str| to |mdstring|.  These are distinct
+  // because the underlying MDString is a UTF-16 based string.  The wchar_t
+  // variant may need to create a MDString that has more characters than the
+  // source |str|, whereas the UTF-8 variant may coalesce characters to form
+  // a single UTF-16 character.
+  bool CopyStringToMDString(const wchar_t *str, unsigned int length,
+                            TypedMDRVA<MDString> *mdstring);
+  bool CopyStringToMDString(const char *str, unsigned int length,
+                            TypedMDRVA<MDString> *mdstring);
+
+  // The common templated code for writing a string
+  template <typename CharType>
+  bool WriteStringCore(const CharType *str, unsigned int length,
+                       MDLocationDescriptor *location);
 };
 
 // Represents an untyped allocated chunk
 class UntypedMDRVA {
  public:
   explicit UntypedMDRVA(MinidumpFileWriter *writer)
       : writer_(writer),
         position_(writer->position()),
         size_(0) {}
 
   // Allocates |size| bytes.  Must not call more than once.
   // Return true on success, or false on failure
   bool Allocate(size_t size);
 
   // Returns the current position or kInvalidMDRVA if allocation failed
-  MDRVA position() const { return position_; }
+  inline MDRVA position() const { return position_; }
 
   // Number of bytes allocated
-  size_t size() const { return size_; }
+  inline size_t size() const { return size_; }
 
   // Return size and position
-  MDLocationDescriptor location() const {
+  inline MDLocationDescriptor location() const {
     MDLocationDescriptor location = { size_, position_ };
     return location;
   }
 
   // Copy |size| bytes starting at |src| into the minidump at |position|
   // Return true on success, or false on failure
   bool Copy(MDRVA position, const void *src, size_t size);
 
   // Copy |size| bytes from |src| to the current position
-  bool Copy(const void *src, size_t size) {
+  inline bool Copy(const void *src, size_t size) {
     return Copy(position_, src, size);
   }
 
  protected:
   // Writer we associate with
   MinidumpFileWriter *writer_;
 
   // Position of the start of the data
@@ -152,17 +184,17 @@ template<typename MDType>
 class TypedMDRVA : public UntypedMDRVA {
  public:
   // Constructs an unallocated MDRVA
   explicit TypedMDRVA(MinidumpFileWriter *writer)
       : UntypedMDRVA(writer),
         data_(),
         allocation_state_(UNALLOCATED) {}
 
-  ~TypedMDRVA() {
+  inline ~TypedMDRVA() {
     // Ensure that the data_ object is written out
     if (allocation_state_ != ARRAY)
       Flush();
   }
 
   // Address of object data_ of MDType.  This is not declared const as the
   // typical usage will be to access the underlying |data_| object as to
   // alter its contents.
@@ -208,11 +240,11 @@ class TypedMDRVA : public UntypedMDRVA {
     ARRAY,
     SINGLE_OBJECT_WITH_ARRAY
   };
 
   MDType data_;
   AllocationState allocation_state_;
 };
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
 
 #endif  // CLIENT_MINIDUMP_FILE_WRITER_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer_unittest.cc
@@ -0,0 +1,162 @@
+// 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.
+
+// Author: waylonis@google.com (Dan Waylonis)
+
+/*
+ g++ -I../ ../common/convert_UTF.c \
+ ../common/string_conversion.cc \
+ minidump_file_writer.cc \
+ minidump_file_writer_unittest.cc \
+ -o minidump_file_writer_unittest
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "minidump_file_writer-inl.h"
+
+using google_breakpad::MinidumpFileWriter;
+
+#define ASSERT_TRUE(cond) \
+if (!(cond)) { \
+  fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \
+    return false; \
+}
+
+#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2))
+#define ASSERT_NE(e1, e2) ASSERT_TRUE((e1) != (e2))
+
+struct StringStructure {
+  unsigned long integer_value;
+  MDLocationDescriptor first_string;
+  MDLocationDescriptor second_string;
+};
+
+struct ArrayStructure {
+  unsigned char char_value;
+  unsigned short short_value;
+  unsigned long long_value;
+};
+
+typedef struct {
+  unsigned long count;
+  ArrayStructure array[0];
+} ObjectAndArrayStructure;
+
+static bool WriteFile(const char *path) {
+  MinidumpFileWriter writer;
+  if (writer.Open(path)) {
+    // Test a single structure
+    google_breakpad::TypedMDRVA<StringStructure> strings(&writer);
+    ASSERT_TRUE(strings.Allocate());
+    strings.get()->integer_value = 0xBEEF;
+    const char *first = "First String";
+    ASSERT_TRUE(writer.WriteString(first, 0, &strings.get()->first_string));
+    const wchar_t *second = L"Second String";
+    ASSERT_TRUE(writer.WriteString(second, 0, &strings.get()->second_string));
+
+    // Test an array structure
+    google_breakpad::TypedMDRVA<ArrayStructure> array(&writer);
+    unsigned int count = 10;
+    ASSERT_TRUE(array.AllocateArray(count));
+    for (unsigned int i = 0; i < count; ++i) {
+      ArrayStructure local;
+      local.char_value = i;
+      local.short_value = i + 1;
+      local.long_value = i + 2;
+      ASSERT_TRUE(array.CopyIndex(i, &local));
+    }
+
+    // Test an object followed by an array
+    google_breakpad::TypedMDRVA<ObjectAndArrayStructure> obj_array(&writer);
+    ASSERT_TRUE(obj_array.AllocateObjectAndArray(count,
+                                                 sizeof(ArrayStructure)));
+    obj_array.get()->count = count;
+    for (unsigned int i = 0; i < count; ++i) {
+      ArrayStructure local;
+      local.char_value = i;
+      local.short_value = i + 1;
+      local.long_value = i + 2;
+      ASSERT_TRUE(obj_array.CopyIndexAfterObject(i, &local, sizeof(local)));
+    }
+  }
+
+  return writer.Close();
+}
+
+static bool CompareFile(const char *path) {
+  unsigned long expected[] = {
+#if defined(__BIG_ENDIAN__)
+    0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000, 
+    0x00000018, 0x00460069, 0x00720073, 0x00740020, 0x00530074, 0x00720069,
+    0x006e0067, 0x00000000, 0x0000001a, 0x00530065, 0x0063006f, 0x006e0064,
+    0x00200053, 0x00740072, 0x0069006e, 0x00670000, 0x00000001, 0x00000002,
+    0x01000002, 0x00000003, 0x02000003, 0x00000004, 0x03000004, 0x00000005,
+    0x04000005, 0x00000006, 0x05000006, 0x00000007, 0x06000007, 0x00000008,
+    0x07000008, 0x00000009, 0x08000009, 0x0000000a, 0x0900000a, 0x0000000b,
+    0x0000000a, 0x00000001, 0x00000002, 0x01000002, 0x00000003, 0x02000003,
+    0x00000004, 0x03000004, 0x00000005, 0x04000005, 0x00000006, 0x05000006,
+    0x00000007, 0x06000007, 0x00000008, 0x07000008, 0x00000009, 0x08000009,
+    0x0000000a, 0x0900000a, 0x0000000b, 0x00000000
+#else
+    0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000,
+    0x00000018, 0x00690046, 0x00730072, 0x00200074, 0x00740053, 0x00690072,
+    0x0067006e, 0x00000000, 0x0000001a, 0x00650053, 0x006f0063, 0x0064006e,
+    0x00530020, 0x00720074, 0x006e0069, 0x00000067, 0x0001da00, 0x00000002,
+    0x0002da01, 0x00000003, 0x0003da02, 0x00000004, 0x0004da03, 0x00000005,
+    0x0005da04, 0x00000006, 0x0006da05, 0x00000007, 0x0007da06, 0x00000008,
+    0x0008da07, 0x00000009, 0x0009da08, 0x0000000a, 0x000ada09, 0x0000000b,
+    0x0000000a, 0x00018700, 0x00000002, 0x00028701, 0x00000003, 0x00038702,
+    0x00000004, 0x00048703, 0x00000005, 0x00058704, 0x00000006, 0x00068705,
+    0x00000007, 0x00078706, 0x00000008, 0x00088707, 0x00000009, 0x00098708,
+    0x0000000a, 0x000a8709, 0x0000000b, 0x00000000, 
+#endif
+  };
+  unsigned int expected_byte_count = sizeof(expected);
+  int fd = open(path, O_RDONLY, 0600);
+  void *buffer = malloc(expected_byte_count);
+  ASSERT_NE(fd, -1);
+  ASSERT_TRUE(buffer);
+  ASSERT_EQ(read(fd, buffer, expected_byte_count), expected_byte_count);
+  ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0);
+  return true;
+}
+
+static bool RunTests() {
+  const char *path = "/tmp/minidump_file_writer_unittest.dmp";
+  ASSERT_TRUE(WriteFile(path));
+  ASSERT_TRUE(CompareFile(path));
+  unlink(path);
+  return true;
+}
+
+extern "C" int main(int argc, const char *argv[]) {
+  return RunTests() ? 0 : 1;
+}
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/Makefile.in
@@ -6,17 +6,17 @@
 # the License. You may obtain a copy of the License at
 # http://www.mozilla.org/MPL/
 #
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
-# The Original Code is Mozilla Airbag integration
+# The Original Code is Mozilla Breakpad integration
 #
 # The Initial Developer of the Original Code is
 # Ted Mielczarek <ted.mielczarek@gmail.com>
 # Portions created by the Initial Developer are Copyright (C) 2006
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.sln
@@ -0,0 +1,36 @@
+
+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
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/Makefile.in
@@ -6,17 +6,17 @@
 # the License. You may obtain a copy of the License at
 # http://www.mozilla.org/MPL/
 #
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
-# The Original Code is Mozilla Airbag integration
+# The Original Code is Mozilla Breakpad integration
 #
 # The Initial Developer of the Original Code is
 # Ted Mielczarek <ted.mielczarek@gmail.com>
 # Portions created by the Initial Developer are Copyright (C) 2006
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #
@@ -37,17 +37,17 @@
 DEPTH		= ../../../../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= handler
-LIBRARY_NAME	= exception_handler
+LIBRARY_NAME	= exception_handler_s
 XPI_NAME 	= crashreporter
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../../..
 DEFINES += -DUNICODE -D_UNICODE
 
 CPPSRCS		= \
 		exception_handler.cc \
 		$(NULL)
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc
@@ -24,221 +24,462 @@
 // 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 <ObjBase.h>
 
+#include <cassert>
 #include <cstdio>
 
 #include "common/windows/string_utils-inl.h"
 
 #include "client/windows/handler/exception_handler.h"
 #include "common/windows/guid_string.h"
-#include "google_airbag/common/minidump_format.h"
 
-namespace google_airbag {
+namespace google_breakpad {
+
+static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
 
-ExceptionHandler *ExceptionHandler::current_handler_ = NULL;
-HANDLE ExceptionHandler::handler_thread_ = NULL;
-CRITICAL_SECTION ExceptionHandler::handler_critical_section_;
-HANDLE ExceptionHandler::handler_start_semaphore_ = NULL;
-HANDLE ExceptionHandler::handler_finish_semaphore_ = NULL;
-ExceptionHandler *ExceptionHandler::requesting_handler_ = NULL;
-DWORD ExceptionHandler::requesting_thread_id_ = 0;
-EXCEPTION_POINTERS *ExceptionHandler::exception_info_ = NULL;
-bool ExceptionHandler::handler_return_value_ = false;
+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,
                                    bool install_handler)
-    : callback_(callback), callback_context_(callback_context),
-      dump_path_(dump_path), dbghelp_module_(NULL),
-      minidump_write_dump_(NULL), previous_handler_(current_handler_),
-      previous_filter_(NULL) {
-  if (!handler_thread_) {
-    // The first time an ExceptionHandler is created, set up the handler
-    // thread and the synchronization primitives.
-    InitializeCriticalSection(&handler_critical_section_);
-    handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
-    handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+    : 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),
+      installed_handler_(install_handler),
+      previous_filter_(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) {
+#if _MSC_VER >= 1400  // MSVC 2005/8
+  previous_iph_ = NULL;
+#endif  // _MSC_VER >= 1400
 
-    DWORD thread_id;
-    handler_thread_ = CreateThread(NULL,         // lpThreadAttributes
-                                   64 * 1024,    // dwStackSize
-                                   ExceptionHandlerThreadMain,
-                                   NULL,         // lpParameter
-                                   0,            // dwCreationFlags
-                                   &thread_id);
-  }
+  // 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);
 
-  UpdateNextID();
+  // Set synchronization primitives and the handler thread.  Each
+  // ExceptionHandler object gets its own handler thread, even if
+  // install_handler is false, because that's the only way to reliably
+  // guarantee sufficient stack space in an exception, and the only 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"));
   }
+
   if (install_handler) {
+    if (!handler_stack_critical_section_initialized_) {
+      InitializeCriticalSection(&handler_stack_critical_section_);
+      handler_stack_critical_section_initialized_ = true;
+    }
+
+    EnterCriticalSection(&handler_stack_critical_section_);
+
+    // 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_->push_back(this);
     previous_filter_ = SetUnhandledExceptionFilter(HandleException);
-    current_handler_ = this;
+
+#if _MSC_VER >= 1400  // MSVC 2005/8
+    previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);
+#endif  // _MSC_VER >= 1400
+
+    LeaveCriticalSection(&handler_stack_critical_section_);
   }
 }
 
 ExceptionHandler::~ExceptionHandler() {
   if (dbghelp_module_) {
     FreeLibrary(dbghelp_module_);
   }
-  if (current_handler_ == this) {
+
+  if (installed_handler_) {
+    EnterCriticalSection(&handler_stack_critical_section_);
+
     SetUnhandledExceptionFilter(previous_filter_);
-    current_handler_ = previous_handler_;
+
+#if _MSC_VER >= 1400  // MSVC 2005/8
+    _set_invalid_parameter_handler(previous_iph_);
+#endif  // _MSC_VER >= 1400
+
+    if (handler_stack_->back() == this) {
+      handler_stack_->pop_back();
+    } else {
+      // 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 =
+               handler_stack_->begin();
+           iterator != handler_stack_->end();
+           ++iterator) {
+        if (*iterator == this) {
+          handler_stack_->erase(iterator);
+        }
+      }
+    }
+
+    if (handler_stack_->empty()) {
+      // When destroying the last ExceptionHandler that installed a handler,
+      // clean up the handler stack.
+      delete handler_stack_;
+      handler_stack_ = NULL;
+    }
+
+    LeaveCriticalSection(&handler_stack_critical_section_);
   }
 
-  if (previous_handler_ == NULL) {
-    // When destroying the last ExceptionHandler, clean up the handler thread
-    // and synchronization primitives.
-    TerminateThread(handler_thread_, 1);
-    handler_thread_ = NULL;
-    DeleteCriticalSection(&handler_critical_section_);
-    CloseHandle(handler_start_semaphore_);
-    handler_start_semaphore_ = NULL;
-    CloseHandle(handler_finish_semaphore_);
-    handler_finish_semaphore_ = NULL;
-  }
+  // 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);
+  assert(self);
+
   while (true) {
-    if (WaitForSingleObject(handler_start_semaphore_, INFINITE) ==
+    if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) ==
         WAIT_OBJECT_0) {
       // Perform the requested action.
-      handler_return_value_ = requesting_handler_->WriteMinidumpWithException(
-          requesting_thread_id_, exception_info_);
+      self->handler_return_value_ = self->WriteMinidumpWithException(
+          self->requesting_thread_id_, self->exception_info_, self->assertion_);
 
       // Allow the requesting thread to proceed.
-      ReleaseSemaphore(handler_finish_semaphore_, 1, NULL);
+      ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL);
     }
   }
 
   // Not reached.  This thread will be terminated by ExceptionHandler's
   // destructor.
   return 0;
 }
 
+// HandleException and HandleInvalidParameter must create an
+// AutoExceptionHandler object to maintain static state and to determine which
+// ExceptionHandler instance to use.  The constructor locates the correct
+// instance, and makes it available through get_handler().  The destructor
+// restores the state in effect prior to allocating the AutoExceptionHandler.
+class AutoExceptionHandler {
+ public:
+  AutoExceptionHandler() {
+    // Increment handler_stack_index_ so that if another Breakpad handler is
+    // registered using this same HandleException function, and it needs to be
+    // called while this handler is running (either becaause this handler
+    // declines to handle the exception, or an exception occurs during
+    // handling), HandleException will find the appropriate ExceptionHandler
+    // object in handler_stack_ to deliver the exception to.
+    //
+    // Because handler_stack_ is addressed in reverse (as |size - index|),
+    // preincrementing handler_stack_index_ avoids needing to subtract 1 from
+    // the argument to |at|.
+    //
+    // The index is maintained instead of popping elements off of the handler
+    // stack and pushing them at the end of this method.  This avoids ruining
+    // the order of elements in the stack in the event that some other thread
+    // decides to manipulate the handler stack (such as creating a new
+    // ExceptionHandler object) while an exception is being handled.
+    EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
+    handler_ = ExceptionHandler::handler_stack_->at(
+        ExceptionHandler::handler_stack_->size() -
+        ++ExceptionHandler::handler_stack_index_);
+    LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
+
+    // In case another exception occurs while this handler is doing its thing,
+    // it should be delivered to the previous filter.
+    SetUnhandledExceptionFilter(handler_->previous_filter_);
+#if _MSC_VER >= 1400  // MSVC 2005/8
+    _set_invalid_parameter_handler(handler_->previous_iph_);
+#endif  // _MSC_VER >= 1400
+  }
+
+  ~AutoExceptionHandler() {
+    // Put things back the way they were before entering this handler.
+    SetUnhandledExceptionFilter(ExceptionHandler::HandleException);
+#if _MSC_VER >= 1400  // MSVC 2005/8
+    _set_invalid_parameter_handler(ExceptionHandler::HandleInvalidParameter);
+#endif  // _MSC_VER >= 1400
+
+    EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
+    --ExceptionHandler::handler_stack_index_;
+    LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
+  }
+
+  ExceptionHandler *get_handler() const { return handler_; }
+
+ private:
+  ExceptionHandler *handler_;
+};
+
 // static
 LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS *exinfo) {
-  return current_handler_->WriteMinidumpOnHandlerThread(exinfo) ?
-      EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+  AutoExceptionHandler auto_exception_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.
+  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.
+    action = EXCEPTION_EXECUTE_HANDLER;
+  } else {
+    // There was an exception, it was a breakpoint or something else ignored
+    // above, or it was passed to the handler, which decided not to handle it.
+    // This could be because the filter callback didn't want it, because
+    // minidump writing failed for some reason, or because the post-minidump
+    // callback function indicated failure.  Give the previous handler a
+    // chance to do something with the exception.  If there is no previous
+    // handler, return EXCEPTION_CONTINUE_SEARCH, which will allow a debugger
+    // or native "crashed" dialog to handle the exception.
+    if (current_handler->previous_filter_) {
+      action = current_handler->previous_filter_(exinfo);
+    } else {
+      action = EXCEPTION_CONTINUE_SEARCH;
+    }
+  }
+
+  return action;
 }
 
-bool ExceptionHandler::WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS *exinfo) {
+#if _MSC_VER >= 1400  // MSVC 2005/8
+// static
+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();
+
+  MDRawAssertionInfo assertion;
+  memset(&assertion, 0, sizeof(assertion));
+  _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),
+               sizeof(assertion.function) / sizeof(assertion.function[0]),
+               _TRUNCATE, L"%s", function);
+  _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)) {
+    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);
+    } 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
+      // function, but now, since this function is no longer registered (and in
+      // fact, no function at all is registered), this will result in the
+      // default code path being taken: _CRT_DEBUGGER_HOOK and _invoke_watson.
+      // Use _invalid_parameter where it exists (in _DEBUG builds) as it passes
+      // more information through.  In non-debug builds, it is not available,
+      // so fall back to using _invalid_parameter_noinfo.  See invarg.c in the
+      // CRT source.
+#ifdef _DEBUG
+      _invalid_parameter(expression, function, file, line, reserved);
+#else  // _DEBUG
+      _invalid_parameter_noinfo();
+#endif  // _DEBUG
+    }
+  }
+
+  // The handler either took care of the invalid parameter problem itself,
+  // or passed it on to another handler.  "Swallow" it by exiting, paralleling
+  // the behavior of "swallowing" exceptions.
+  exit(0);
+}
+#endif  // _MSC_VER >= 1400
+
+bool ExceptionHandler::WriteMinidumpOnHandlerThread(
+    EXCEPTION_POINTERS *exinfo, MDRawAssertionInfo *assertion) {
   EnterCriticalSection(&handler_critical_section_);
 
   // Set up data to be passed in to the handler thread.
-  requesting_handler_ = this;
   requesting_thread_id_ = GetCurrentThreadId();
   exception_info_ = exinfo;
+  assertion_ = assertion;
 
   // This causes the handler thread to call WriteMinidumpWithException.
   ReleaseSemaphore(handler_start_semaphore_, 1, NULL);
 
   // Wait until WriteMinidumpWithException is done and collect its return value.
   WaitForSingleObject(handler_finish_semaphore_, INFINITE);
   bool status = handler_return_value_;
 
   // Clean up.
-  requesting_handler_ = NULL;
   requesting_thread_id_ = 0;
   exception_info_ = NULL;
+  assertion_ = NULL;
 
   LeaveCriticalSection(&handler_critical_section_);
 
   return status;
 }
 
 bool ExceptionHandler::WriteMinidump() {
-  bool success = WriteMinidumpOnHandlerThread(NULL);
+  bool success = WriteMinidumpOnHandlerThread(NULL, NULL);
   UpdateNextID();
   return success;
 }
 
 // static
 bool ExceptionHandler::WriteMinidump(const wstring &dump_path,
                                      MinidumpCallback callback,
                                      void *callback_context) {
-  ExceptionHandler handler(dump_path, callback, callback_context, false);
+  ExceptionHandler handler(dump_path, NULL, callback, callback_context, false);
   return handler.WriteMinidump();
 }
 
-bool ExceptionHandler::WriteMinidumpWithException(DWORD requesting_thread_id,
-                                                  EXCEPTION_POINTERS *exinfo) {
-  wchar_t dump_file_name[MAX_PATH];
-  WindowsStringUtils::safe_swprintf(dump_file_name, MAX_PATH, L"%s\\%s.dmp",
-                                    dump_path_.c_str(),
-                                    next_minidump_id_.c_str());
+bool ExceptionHandler::WriteMinidumpWithException(
+    DWORD requesting_thread_id,
+    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
+  // HandleException to call any previous handler or return
+  // EXCEPTION_CONTINUE_SEARCH on the exception thread, allowing it to appear
+  // as though this handler were not present at all.
+  if (filter_ && !filter_(callback_context_, exinfo, assertion)) {
+    return false;
+  }
 
   bool success = false;
   if (minidump_write_dump_) {
-    HANDLE dump_file = CreateFile(dump_file_name,
+    HANDLE dump_file = CreateFile(next_minidump_path_c_,
                                   GENERIC_WRITE,
                                   FILE_SHARE_WRITE,
                                   NULL,
                                   CREATE_ALWAYS,
                                   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 MDRawAirbagInfo stream to the minidump, to provide additional
-      // information about the exception handler to the Airbag processor.  The
+      // 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 Airbag processor does not require this information but
-      // can function better with Airbag-generated dumps when it is present.
+      // 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.
-      MDRawAirbagInfo airbag_info;
-      airbag_info.validity = MD_AIRBAG_INFO_VALID_DUMP_THREAD_ID |
-                             MD_AIRBAG_INFO_VALID_REQUESTING_THREAD_ID;
-      airbag_info.dump_thread_id = GetCurrentThreadId();
-      airbag_info.requesting_thread_id = requesting_thread_id;
+      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;
 
-      MINIDUMP_USER_STREAM airbag_info_stream;
-      airbag_info_stream.Type = MD_AIRBAG_INFO_STREAM;
-      airbag_info_stream.BufferSize = sizeof(airbag_info);
-      airbag_info_stream.Buffer = &airbag_info;
+      // 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 = &airbag_info_stream;
+      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);
 
       CloseHandle(dump_file);
     }
   }
 
   if (callback_) {
-    callback_(next_minidump_id_, callback_context_, success);
+    success = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
+                        exinfo, assertion, success);
   }
-  // TODO(bryner): log an error on failure
 
   return success;
 }
 
 void ExceptionHandler::UpdateNextID() {
   GUID id;
   CoCreateGuid(&id);
   next_minidump_id_ = GUIDString::GUIDToWString(&id);
+  next_minidump_id_c_ = next_minidump_id_.c_str();
+
+  wchar_t minidump_path[MAX_PATH];
+  swprintf(minidump_path, MAX_PATH, L"%s\\%s.dmp",
+           dump_path_c_, next_minidump_id_c_);
+  GB_WSU_SAFE_SWPRINTF_TERMINATE(minidump_path, MAX_PATH);
+  next_minidump_path_ = minidump_path;
+  next_minidump_path_c_ = next_minidump_path_.c_str();
 }
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h
@@ -54,62 +54,109 @@
 // 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__
 
+#include <stdlib.h>
 #include <Windows.h>
 #include <DbgHelp.h>
 
 #pragma warning( push )
 // Disable exception handler warnings.
 #pragma warning( disable : 4530 ) 
 
 #include <string>
+#include <vector>
 
-namespace google_airbag {
+#include "google_breakpad/common/minidump_format.h"
 
+namespace google_breakpad {
+
+using std::vector;
 using std::wstring;
 
 class ExceptionHandler {
  public:
+  // A callback function to run before Breakpad performs any substantial
+  // processing of an exception.  A FilterCallback is called before writing
+  // a minidump.  context is the parameter supplied by the user as
+  // callback_context when the handler was created.  exinfo points to the
+  // exception record, if any; assertion points to assertion information,
+  // if any.
+  //
+  // If a FilterCallback returns true, Breakpad will continue processing,
+  // 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);
+
   // A callback function to run after the minidump has been written.
   // minidump_id is a unique id for the dump, so the minidump
-  // file is <dump_path>\<minidump_id>.dmp.  succeeded indicates whether
-  // a minidump file was successfully written.
-  typedef void (*MinidumpCallback)(const wstring &minidump_id,
-                                   void *context, bool succeeded);
+  // file is <dump_path>\<minidump_id>.dmp.  context is the parameter supplied
+  // by the user as callback_context when the handler was created.  exinfo
+  // points to the exception record, or NULL if no exception occurred.
+  // succeeded indicates whether a minidump file was successfully written.
+  // assertion points to information about an assertion if the handler was
+  // invoked by an assertion.
+  //
+  // If an exception occurred and the callback returns true, Breakpad will treat
+  // the exception as fully-handled, suppressing any other handlers from being
+  // notified of the exception.  If the callback returns false, Breakpad will
+  // treat the exception as unhandled, and allow another handler to handle it.
+  // If there are no other handlers, Breakpad will report the exception to the
+  // system as unhandled, allowing a debugger or native crash dialog the
+  // opportunity to handle the exception.  Most callback implementations
+  // 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,
+                                   bool succeeded);
 
   // Creates a new ExceptionHandler instance to handle writing minidumps.
+  // Before writing a minidump, the optional filter callback will be called.
+  // Its return value determines whether or not Breakpad should write a minidump.
   // Minidump files will be written to dump_path, and the optional callback
   // is called after writing the dump file, as described above.
   // If install_handler is true, then a minidump will be written whenever
   // an unhandled exception occurs.  If it is false, minidumps will only
   // be written when WriteMinidump is called.
-  ExceptionHandler(const wstring &dump_path, MinidumpCallback callback,
+  ExceptionHandler(const wstring &dump_path,
+                   FilterCallback filter, MinidumpCallback callback,
                    void *callback_context, bool install_handler);
   ~ExceptionHandler();
 
   // Get and set the minidump path.
   wstring dump_path() const { return dump_path_; }
-  void set_dump_path(const wstring &dump_path) { dump_path_ = dump_path; }
+  void set_dump_path(const wstring &dump_path) {
+    dump_path_ = dump_path;
+    dump_path_c_ = dump_path_.c_str();
+    UpdateNextID();  // Necessary to put dump_path_ in next_minidump_path_.
+  }
 
   // Writes a minidump immediately.  This can be used to capture the
   // execution state independently of a crash.  Returns true on success.
   bool WriteMinidump();
 
   // Convenience form of WriteMinidump which does not require an
   // ExceptionHandler instance.
   static bool WriteMinidump(const wstring &dump_path,
                             MinidumpCallback callback, void *callback_context);
 
  private:
+  friend class AutoExceptionHandler;
+
   // Function pointer type for MiniDumpWriteDump, which is looked up
   // dynamically.
   typedef BOOL (WINAPI *MiniDumpWriteDump_type)(
       HANDLE hProcess,
       DWORD dwPid,
       HANDLE hFile,
       MINIDUMP_TYPE DumpType,
       CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
@@ -118,88 +165,156 @@ class ExceptionHandler {
 
   // Runs the main loop for the exception handler thread.
   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);
 
+#if _MSC_VER >= 1400  // MSVC 2005/8
+  // This function will be called by some CRT functions when they detect
+  // that they were passed an invalid parameter.  Note that in _DEBUG builds,
+  // 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,
+                                     unsigned int line,
+                                     uintptr_t reserved);
+#endif  // _MSC_VER >= 1400
+
   // This is called on the exception thread or on another thread that
   // the user wishes to produce a dump from.  It calls
   // WriteMinidumpWithException on the handler thread, avoiding stack
   // overflows and inconsistent dumps due to writing the dump from
   // the exception thread.  If the dump is requested as a result of an
   // exception, exinfo contains exception information, otherwise, it
-  // is NULL.
-  bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS *exinfo);
+  // 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);
 
   // 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
   // that requested the dump.  If the dump is requested as a result of
   // an exception, exinfo contains exception information, otherwise,
   // it is NULL.
   bool WriteMinidumpWithException(DWORD requesting_thread_id,
-                                  EXCEPTION_POINTERS *exinfo);
+                                  EXCEPTION_POINTERS *exinfo,
+                                  MDRawAssertionInfo *assertion);
 
-  // Generates a new ID and stores it in next_minidump_id_.
+  // 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();
 
+  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.
   wstring dump_path_;
+
+  // The basename of the next minidump to be written, without the extension.
   wstring next_minidump_id_;
 
+  // The full pathname of the next minidump to be written, including the file
+  // extension.
+  wstring next_minidump_path_;
+
+  // Pointers to C-string representations of the above.  These are set when
+  // the above wstring versions are set in order to avoid calling c_str during
+  // an exception, as c_str may attempt to allocate heap memory.  These
+  // 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_;
+
   HMODULE dbghelp_module_;
   MiniDumpWriteDump_type minidump_write_dump_;
 
-  ExceptionHandler *previous_handler_;  // current_handler_ before us
+  // True if the ExceptionHandler installed an unhandled exception filter
+  // when created (with an install_handler parameter set to true).
+  bool installed_handler_;
+
+  // When installed_handler_ is true, previous_filter_ is the unhandled
+  // exception filter that was set prior to installing ExceptionHandler as
+  // the unhandled exception filter and pointing it to |this|.  NULL indicates
+  // that there is no previous unhandled exception filter.
   LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_;
 
-  // the currently-installed ExceptionHandler, of which there can be only 1
-  static ExceptionHandler *current_handler_;
+#if _MSC_VER >= 1400  // MSVC 2005/8
+  // Beginning in VC 8, the CRT provides an invalid parameter handler that will
+  // be called when some CRT functions are passed invalid parameters.  In
+  // earlier CRTs, the same conditions would cause unexpected behavior or
+  // crashes.
+  _invalid_parameter_handler previous_iph_;
+#endif  // _MSC_VER >= 1400
 
-  // The exception handler thread, if one has been created.
-  static HANDLE handler_thread_;
+  // The exception handler thread.
+  HANDLE handler_thread_;
 
   // The critical section enforcing the requirement that only one exception be
-  // handled at a time.
-  static CRITICAL_SECTION handler_critical_section_;
+  // handled by a handler at a time.
+  CRITICAL_SECTION handler_critical_section_;
 
   // 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.
-  static HANDLE handler_start_semaphore_;
-  static HANDLE handler_finish_semaphore_;
+  HANDLE handler_start_semaphore_;
+  HANDLE handler_finish_semaphore_;
 
-  // The next 3 fields are static data passed from the requesting thread to
+  // The next 2 fields contain data passed from the requesting thread to
   // the handler thread.
 
-  // The ExceptionHandler through which a request to write a dump was routed.
-  // This will be the same as current_handler_ for exceptions, but
-  // user-requested dumps may be routed through any live ExceptionHandler.
-  static ExceptionHandler *requesting_handler_;
-
   // The thread ID of the thread requesting the dump (either the exception
   // thread or any other thread that called WriteMinidump directly).
-  static DWORD requesting_thread_id_;
+  DWORD requesting_thread_id_;
 
   // The exception info passed to the exception handler on the exception
   // thread, if an exception occurred.  NULL for user-requested dumps.
-  static 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_;
 
   // The return value of the handler, passed from the handler thread back to
   // the requesting thread.
-  static bool handler_return_value_;
+  bool handler_return_value_;
+
+  // 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_;
+
+  // 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
+  // means the next-to-last entry, and so on.  This is used by HandleException
+  // to support multiple stacked Breakpad handlers.
+  static LONG handler_stack_index_;
+
+  // handler_stack_critical_section_ guards operations on handler_stack_ and
+  // handler_stack_index_.
+  static CRITICAL_SECTION handler_stack_critical_section_;
+
+  // True when handler_stack_critical_section_ has been initialized.
+  static bool handler_stack_critical_section_initialized_;
 
   // disallow copy ctor and operator=
   explicit ExceptionHandler(const ExceptionHandler &);
   void operator=(const ExceptionHandler &);
 };
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
 
 #pragma warning( pop )
 
 #endif  // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.vcproj
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.vcproj
@@ -290,17 +290,17 @@
 				RelativePath=".\exception_handler.h"
 				>
 			</File>
 			<File
 				RelativePath="..\..\..\common\windows\guid_string.h"
 				>
 			</File>
 			<File
-				RelativePath="..\..\..\google_airbag\common\minidump_format.h"
+				RelativePath="..\..\..\google_breakpad\common\minidump_format.h"
 				>
 			</File>
 			<File
 				RelativePath="..\..\..\common\windows\string_utils-inl.h"
 				>
 			</File>
 		</Filter>
 		<Filter
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/Makefile.in
@@ -6,17 +6,17 @@
 # the License. You may obtain a copy of the License at
 # http://www.mozilla.org/MPL/
 #
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
-# The Original Code is Mozilla Airbag integration
+# The Original Code is Mozilla Breakpad integration
 #
 # The Initial Developer of the Original Code is
 # Ted Mielczarek <ted.mielczarek@gmail.com>
 # Portions created by the Initial Developer are Copyright (C) 2006
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #
@@ -37,17 +37,17 @@
 DEPTH		= ../../../../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= sender
-LIBRARY_NAME	= crash_report_sender
+LIBRARY_NAME	= crash_report_sender_s
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../../..
 DEFINES += -DUNICODE -D_UNICODE
 
 CPPSRCS		= \
 		crash_report_sender.cc \
 		$(NULL)
 
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc
@@ -28,20 +28,31 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Disable exception handler warnings.
 #pragma warning( disable : 4530 )
 
 #include "client/windows/sender/crash_report_sender.h"
 #include "common/windows/http_upload.h"
 
-namespace google_airbag {
+namespace google_breakpad {
 
 // static
-bool CrashReportSender::SendCrashReport(
+ReportResult CrashReportSender::SendCrashReport(
     const wstring &url, const map<wstring, wstring> &parameters,
-    const wstring &dump_file_name) {
+    const wstring &dump_file_name, wstring *report_code) {
+
+  int http_response = 0;
+  bool result = HTTPUpload::SendRequest(
+    url, parameters, dump_file_name, L"upload_file_minidump", report_code,
+    &http_response);
 
-  return HTTPUpload::SendRequest(url, parameters, dump_file_name,
-                                 L"upload_file_minidump");
+  if (result) {
+    return RESULT_SUCCEEDED;
+  } else if (http_response == 400) {  // TODO: update if/when the server
+                                      //       switches to a different code
+    return RESULT_REJECTED;
+  } else {
+    return RESULT_FAILED;
+  }
 }
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.h
@@ -40,39 +40,51 @@
 
 #pragma warning( push )
 // Disable exception handler warnings.
 #pragma warning( disable : 4530 ) 
 
 #include <map>
 #include <string>
 
-namespace google_airbag {
+namespace google_breakpad {
 
 using std::wstring;
 using std::map;
 
+typedef enum {
+  RESULT_FAILED = 0,  // Failed to communicate with the server; try later.
+  RESULT_REJECTED,    // Successfully sent the crash report, but the
+                      // server rejected it; don't resend this report.
+  RESULT_SUCCEEDED    // The server accepted the crash report.
+} ReportResult;
+
 class CrashReportSender {
  public:
   // Sends the specified minidump file, along with the map of
   // name value pairs, as a multipart POST request to the given URL.
   // Parameter names must contain only printable ASCII characters,
   // and may not contain a quote (") character.
-  // Only HTTP(S) URLs are currently supported.  Returns true on success.
-  // TODO(bryner): we should expose the response to the caller.
-  static bool SendCrashReport(const wstring &url,
-                              const map<wstring, wstring> &parameters,
-                              const wstring &dump_file_name);
+  // Only HTTP(S) URLs are currently supported.  The return value indicates
+  // the result of the operation (see above for possible results).
+  // If report_code is non-NULL and the report is sent successfully (that is,
+  // the return value is RESULT_SUCCEEDED), a code uniquely identifying the
+  // report will be returned in report_code.
+  // (Otherwise, report_code will be unchanged.)
+  static ReportResult SendCrashReport(const wstring &url,
+                                      const map<wstring, wstring> &parameters,
+                                      const wstring &dump_file_name,
+                                      wstring *report_code);
 
  private:
   // No instances of this class should be created.
   // Disallow all constructors, destructors, and operator=.
   CrashReportSender();
   explicit CrashReportSender(const CrashReportSender &);
   void operator=(const CrashReportSender &);
   ~CrashReportSender();
 };
 
-}  // namespace google_airbag
+}  // namespace google_breakpad
 
 #pragma warning( pop )
 
 #endif  // CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+Author: Mark E. Davis, 1994.
+Rev History: Rick McGowan, fixes & updates May 2001.
+Sept 2001: fixed const & error conditions per
+mods suggested by S. Parent & A. Lillich.
+June 2002: Tim Dodd added detection and handling of incomplete
+source sequences, enhanced error detection, added casts
+to eliminate compiler warnings.
+July 2003: slight mods to back out aggressive FFFE detection.
+Jan 2004: updated switches in from-UTF8 conversions.
+Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+
+See the header file "ConvertUTF.h" for complete documentation.
+
+------------------------------------------------------------------------ */
+
+
+#include "convert_UTF.h"
+#ifdef CVTUTF_DEBUG
+#include <stdio.h>
+#endif
+
+static const int halfShift  = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START  (UTF32)0xD800
+#define UNI_SUR_HIGH_END    (UTF32)0xDBFF
+#define UNI_SUR_LOW_START   (UTF32)0xDC00
+#define UNI_SUR_LOW_END     (UTF32)0xDFFF
+#define false	   0
+#define true	    1
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd,
+                                      UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+  ConversionResult result = conversionOK;
+  const UTF32* source = *sourceStart;
+  UTF16* target = *targetStart;
+  while (source < sourceEnd) {
+    UTF32 ch;
+    if (target >= targetEnd) {
+	    result = targetExhausted; break;
+    }
+    ch = *source++;
+    if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+	    /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+	    if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+        if (flags == strictConversion) {
+          --source; /* return to the illegal value itself */
+          result = sourceIllegal;
+          break;
+        } else {
+          *target++ = UNI_REPLACEMENT_CHAR;
+        }
+	    } else {
+        *target++ = (UTF16)ch; /* normal case */
+	    }
+    } else if (ch > UNI_MAX_LEGAL_UTF32) {
+	    if (flags == strictConversion) {
+        result = sourceIllegal;
+	    } else {
+        *target++ = UNI_REPLACEMENT_CHAR;
+	    }