google-breakpad: Merge with upstream breakpad r981

BUG=none
TEST=Verified the following:
1. emerge google-breadpad for x86-generic, arm-generic and amd64-generic
2. cros_run_unit_tests google-breakpad for x86-generic and amd64-generic
3. Run the following autotest tests on a Cr48:
   - logging_CrashSender
   - logging_UserCrash

Change-Id: I41dcafc2cadd3242b64813ad5a745a67dd9fc178
diff --git a/Makefile.am b/Makefile.am
index 7e2bc45..f884865 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,6 +33,16 @@
 # This allows #includes to be relative to src/
 AM_CPPFLAGS = -I$(top_srcdir)/src
 
+if GCC
+# These are good warnings to be treated as errors
+AM_CXXFLAGS = \
+	-Werror=non-virtual-dtor \
+	-Werror=vla \
+	-Werror=unused-variable \
+	-Werror=missing-braces \
+	-Werror=overloaded-virtual
+endif
+
 # Specify include paths for ac macros
 ACLOCAL_AMFLAGS = -I m4
 
@@ -65,15 +75,14 @@
 src_client_linux_libbreakpad_client_a_SOURCES = \
 	src/client/linux/crash_generation/crash_generation_client.cc \
 	src/client/linux/handler/exception_handler.cc \
+	src/client/linux/log/log.cc \
 	src/client/linux/minidump_writer/linux_dumper.cc \
-	src/client/linux/minidump_writer/linux_core_dumper.cc \
 	src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
 	src/client/linux/minidump_writer/minidump_writer.cc \
 	src/client/minidump_file_writer.cc \
 	src/common/convert_UTF.c \
 	src/common/md5.cc \
 	src/common/string_conversion.cc \
-	src/common/linux/elf_core_dump.cc \
 	src/common/linux/file_id.cc \
 	src/common/linux/guid_creator.cc \
 	src/common/linux/memory_mapped_file.cc \
@@ -304,6 +313,7 @@
 	src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
 	src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
 	src/client/linux/minidump_writer/minidump_writer_unittest.cc \
+	src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
 	src/common/linux/linux_libc_support_unittest.cc \
 	src/common/linux/tests/crash_generator.cc \
 	src/common/memory_unittest.cc \
@@ -324,6 +334,7 @@
 	-I$(top_srcdir)/src/testing
 src_client_linux_linux_client_unittest_LDADD = \
 	src/client/linux/handler/exception_handler.o \
+	src/client/linux/log/log.o \
 	src/client/linux/crash_generation/crash_generation_client.o \
 	src/client/linux/minidump_writer/linux_dumper.o \
 	src/client/linux/minidump_writer/linux_core_dumper.o \
@@ -367,12 +378,12 @@
 src_tools_linux_symupload_minidump_upload_SOURCES = \
 	src/common/linux/http_upload.cc \
 	src/tools/linux/symupload/minidump_upload.cc
-src_tools_linux_symupload_minidump_upload_LDFLAGS = -ldl
+src_tools_linux_symupload_minidump_upload_LDADD = -ldl
 
 src_tools_linux_symupload_sym_upload_SOURCES = \
 	src/common/linux/http_upload.cc \
 	src/tools/linux/symupload/sym_upload.cc
-src_tools_linux_symupload_sym_upload_LDFLAGS = -ldl
+src_tools_linux_symupload_sym_upload_LDADD = -ldl
 
 src_common_dumper_unittest_SOURCES = \
 	src/common/byte_cursor_unittest.cc \
@@ -430,7 +441,9 @@
 
 if !DISABLE_CORE2MD
 src_tools_linux_core2md_core2md_SOURCES = \
-	src/tools/linux/core2md/core2md.cc
+	src/tools/linux/core2md/core2md.cc \
+	src/client/linux/minidump_writer/linux_core_dumper.cc \
+	src/common/linux/elf_core_dump.cc
 src_tools_linux_core2md_core2md_LDADD = \
 	src/client/linux/libbreakpad_client.a
 endif !DISABLE_CORE2MD
diff --git a/Makefile.in b/Makefile.in
index 4683cca..b96dfa6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -178,28 +178,26 @@
 am__src_client_linux_libbreakpad_client_a_SOURCES_DIST =  \
 	src/client/linux/crash_generation/crash_generation_client.cc \
 	src/client/linux/handler/exception_handler.cc \
+	src/client/linux/log/log.cc \
 	src/client/linux/minidump_writer/linux_dumper.cc \
-	src/client/linux/minidump_writer/linux_core_dumper.cc \
 	src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
 	src/client/linux/minidump_writer/minidump_writer.cc \
 	src/client/minidump_file_writer.cc src/common/convert_UTF.c \
 	src/common/md5.cc src/common/string_conversion.cc \
-	src/common/linux/elf_core_dump.cc src/common/linux/file_id.cc \
-	src/common/linux/guid_creator.cc \
+	src/common/linux/file_id.cc src/common/linux/guid_creator.cc \
 	src/common/linux/memory_mapped_file.cc \
 	src/common/linux/safe_readlink.cc
 am__dirstamp = $(am__leading_dot)dirstamp
 @LINUX_HOST_TRUE@am_src_client_linux_libbreakpad_client_a_OBJECTS = src/client/linux/crash_generation/crash_generation_client.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/linux/handler/exception_handler.$(OBJEXT) \
+@LINUX_HOST_TRUE@	src/client/linux/log/log.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_dumper.$(OBJEXT) \
-@LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_ptrace_dumper.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/minidump_writer.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/minidump_file_writer.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/convert_UTF.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/md5.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/string_conversion.$(OBJEXT) \
-@LINUX_HOST_TRUE@	src/common/linux/elf_core_dump.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/linux/file_id.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/linux/guid_creator.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/linux/memory_mapped_file.$(OBJEXT) \
@@ -404,6 +402,7 @@
 	src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
 	src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
 	src/client/linux/minidump_writer/minidump_writer_unittest.cc \
+	src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
 	src/common/linux/linux_libc_support_unittest.cc \
 	src/common/linux/tests/crash_generator.cc \
 	src/common/memory_unittest.cc src/common/tests/file_utils.cc \
@@ -418,6 +417,7 @@
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-linux_core_dumper_unittest.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-linux_ptrace_dumper_unittest.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@	src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/linux/src_client_linux_linux_client_unittest-linux_libc_support_unittest.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/linux/tests/src_client_linux_linux_client_unittest-crash_generator.$(OBJEXT) \
 @LINUX_HOST_TRUE@	src/common/src_client_linux_linux_client_unittest-memory_unittest.$(OBJEXT) \
@@ -921,8 +921,12 @@
 	$(am_src_processor_synth_minidump_unittest_OBJECTS)
 src_processor_synth_minidump_unittest_LDADD = $(LDADD)
 am__src_tools_linux_core2md_core2md_SOURCES_DIST =  \
-	src/tools/linux/core2md/core2md.cc
-@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_core2md_core2md_OBJECTS = src/tools/linux/core2md/core2md.$(OBJEXT)
+	src/tools/linux/core2md/core2md.cc \
+	src/client/linux/minidump_writer/linux_core_dumper.cc \
+	src/common/linux/elf_core_dump.cc
+@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_core2md_core2md_OBJECTS = src/tools/linux/core2md/core2md.$(OBJEXT) \
+@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT) \
+@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/common/linux/elf_core_dump.$(OBJEXT)
 src_tools_linux_core2md_core2md_OBJECTS =  \
 	$(am_src_tools_linux_core2md_core2md_OBJECTS)
 @DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_DEPENDENCIES = src/client/linux/libbreakpad_client.a
@@ -985,11 +989,7 @@
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/symupload/minidump_upload.$(OBJEXT)
 src_tools_linux_symupload_minidump_upload_OBJECTS =  \
 	$(am_src_tools_linux_symupload_minidump_upload_OBJECTS)
-src_tools_linux_symupload_minidump_upload_LDADD = $(LDADD)
-src_tools_linux_symupload_minidump_upload_LINK = $(CXXLD) \
-	$(AM_CXXFLAGS) $(CXXFLAGS) \
-	$(src_tools_linux_symupload_minidump_upload_LDFLAGS) \
-	$(LDFLAGS) -o $@
+src_tools_linux_symupload_minidump_upload_DEPENDENCIES =
 am__src_tools_linux_symupload_sym_upload_SOURCES_DIST =  \
 	src/common/linux/http_upload.cc \
 	src/tools/linux/symupload/sym_upload.cc
@@ -997,10 +997,7 @@
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/symupload/sym_upload.$(OBJEXT)
 src_tools_linux_symupload_sym_upload_OBJECTS =  \
 	$(am_src_tools_linux_symupload_sym_upload_OBJECTS)
-src_tools_linux_symupload_sym_upload_LDADD = $(LDADD)
-src_tools_linux_symupload_sym_upload_LINK = $(CXXLD) $(AM_CXXFLAGS) \
-	$(CXXFLAGS) $(src_tools_linux_symupload_sym_upload_LDFLAGS) \
-	$(LDFLAGS) -o $@
+src_tools_linux_symupload_sym_upload_DEPENDENCIES =
 SCRIPTS = $(noinst_SCRIPTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
 depcomp = $(SHELL) $(top_srcdir)/autotools/depcomp
@@ -1215,6 +1212,15 @@
 # This allows #includes to be relative to src/
 AM_CPPFLAGS = -I$(top_srcdir)/src
 
+# These are good warnings to be treated as errors
+@GCC_TRUE@AM_CXXFLAGS = \
+@GCC_TRUE@	-Werror=non-virtual-dtor \
+@GCC_TRUE@	-Werror=vla \
+@GCC_TRUE@	-Werror=unused-variable \
+@GCC_TRUE@	-Werror=missing-braces \
+@GCC_TRUE@	-Werror=overloaded-virtual
+
+
 # Specify include paths for ac macros
 ACLOCAL_AMFLAGS = -I m4
 dist_doc_DATA = \
@@ -1230,15 +1236,14 @@
 @LINUX_HOST_TRUE@src_client_linux_libbreakpad_client_a_SOURCES = \
 @LINUX_HOST_TRUE@	src/client/linux/crash_generation/crash_generation_client.cc \
 @LINUX_HOST_TRUE@	src/client/linux/handler/exception_handler.cc \
+@LINUX_HOST_TRUE@	src/client/linux/log/log.cc \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_dumper.cc \
-@LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_core_dumper.cc \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/minidump_writer.cc \
 @LINUX_HOST_TRUE@	src/client/minidump_file_writer.cc \
 @LINUX_HOST_TRUE@	src/common/convert_UTF.c \
 @LINUX_HOST_TRUE@	src/common/md5.cc \
 @LINUX_HOST_TRUE@	src/common/string_conversion.cc \
-@LINUX_HOST_TRUE@	src/common/linux/elf_core_dump.cc \
 @LINUX_HOST_TRUE@	src/common/linux/file_id.cc \
 @LINUX_HOST_TRUE@	src/common/linux/guid_creator.cc \
 @LINUX_HOST_TRUE@	src/common/linux/memory_mapped_file.cc \
@@ -1386,6 +1391,7 @@
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/minidump_writer_unittest.cc \
+@LINUX_HOST_TRUE@	src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
 @LINUX_HOST_TRUE@	src/common/linux/linux_libc_support_unittest.cc \
 @LINUX_HOST_TRUE@	src/common/linux/tests/crash_generator.cc \
 @LINUX_HOST_TRUE@	src/common/memory_unittest.cc \
@@ -1407,6 +1413,7 @@
 
 @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDADD = \
 @LINUX_HOST_TRUE@	src/client/linux/handler/exception_handler.o \
+@LINUX_HOST_TRUE@	src/client/linux/log/log.o \
 @LINUX_HOST_TRUE@	src/client/linux/crash_generation/crash_generation_client.o \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_dumper.o \
 @LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_core_dumper.o \
@@ -1450,12 +1457,12 @@
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/http_upload.cc \
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/symupload/minidump_upload.cc
 
-@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_LDFLAGS = -ldl
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_LDADD = -ldl
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_SOURCES = \
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/http_upload.cc \
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/symupload/sym_upload.cc
 
-@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_LDFLAGS = -ldl
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_LDADD = -ldl
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_SOURCES = \
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/byte_cursor_unittest.cc \
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf_cfi_to_module.cc \
@@ -1511,7 +1518,9 @@
 
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_LDADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
 @DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_SOURCES = \
-@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/core2md/core2md.cc
+@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/core2md/core2md.cc \
+@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/client/linux/minidump_writer/linux_core_dumper.cc \
+@DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/common/linux/elf_core_dump.cc
 
 @DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_LDADD = \
 @DISABLE_CORE2MD_FALSE@@LINUX_HOST_TRUE@	src/client/linux/libbreakpad_client.a
@@ -2216,6 +2225,15 @@
 src/client/linux/handler/exception_handler.$(OBJEXT):  \
 	src/client/linux/handler/$(am__dirstamp) \
 	src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/log/$(am__dirstamp):
+	@$(MKDIR_P) src/client/linux/log
+	@: > src/client/linux/log/$(am__dirstamp)
+src/client/linux/log/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/client/linux/log/$(DEPDIR)
+	@: > src/client/linux/log/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/log/log.$(OBJEXT):  \
+	src/client/linux/log/$(am__dirstamp) \
+	src/client/linux/log/$(DEPDIR)/$(am__dirstamp)
 src/client/linux/minidump_writer/$(am__dirstamp):
 	@$(MKDIR_P) src/client/linux/minidump_writer
 	@: > src/client/linux/minidump_writer/$(am__dirstamp)
@@ -2225,9 +2243,6 @@
 src/client/linux/minidump_writer/linux_dumper.$(OBJEXT):  \
 	src/client/linux/minidump_writer/$(am__dirstamp) \
 	src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
-src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT):  \
-	src/client/linux/minidump_writer/$(am__dirstamp) \
-	src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
 src/client/linux/minidump_writer/linux_ptrace_dumper.$(OBJEXT):  \
 	src/client/linux/minidump_writer/$(am__dirstamp) \
 	src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
@@ -2260,9 +2275,6 @@
 src/common/linux/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/common/linux/$(DEPDIR)
 	@: > src/common/linux/$(DEPDIR)/$(am__dirstamp)
-src/common/linux/elf_core_dump.$(OBJEXT):  \
-	src/common/linux/$(am__dirstamp) \
-	src/common/linux/$(DEPDIR)/$(am__dirstamp)
 src/common/linux/file_id.$(OBJEXT): src/common/linux/$(am__dirstamp) \
 	src/common/linux/$(DEPDIR)/$(am__dirstamp)
 src/common/linux/guid_creator.$(OBJEXT):  \
@@ -2473,6 +2485,9 @@
 src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest.$(OBJEXT):  \
 	src/client/linux/minidump_writer/$(am__dirstamp) \
 	src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.$(OBJEXT):  \
+	src/client/linux/minidump_writer/$(am__dirstamp) \
+	src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
 src/common/linux/src_client_linux_linux_client_unittest-linux_libc_support_unittest.$(OBJEXT):  \
 	src/common/linux/$(am__dirstamp) \
 	src/common/linux/$(DEPDIR)/$(am__dirstamp)
@@ -3000,6 +3015,12 @@
 src/tools/linux/core2md/core2md.$(OBJEXT):  \
 	src/tools/linux/core2md/$(am__dirstamp) \
 	src/tools/linux/core2md/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT):  \
+	src/client/linux/minidump_writer/$(am__dirstamp) \
+	src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/elf_core_dump.$(OBJEXT):  \
+	src/common/linux/$(am__dirstamp) \
+	src/common/linux/$(DEPDIR)/$(am__dirstamp)
 src/tools/linux/core2md/core2md$(EXEEXT): $(src_tools_linux_core2md_core2md_OBJECTS) $(src_tools_linux_core2md_core2md_DEPENDENCIES) src/tools/linux/core2md/$(am__dirstamp)
 	@rm -f src/tools/linux/core2md/core2md$(EXEEXT)
 	$(CXXLINK) $(src_tools_linux_core2md_core2md_OBJECTS) $(src_tools_linux_core2md_core2md_LDADD) $(LIBS)
@@ -3085,19 +3106,20 @@
 	src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
 src/tools/linux/symupload/minidump_upload$(EXEEXT): $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_DEPENDENCIES) src/tools/linux/symupload/$(am__dirstamp)
 	@rm -f src/tools/linux/symupload/minidump_upload$(EXEEXT)
-	$(src_tools_linux_symupload_minidump_upload_LINK) $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_LDADD) $(LIBS)
+	$(CXXLINK) $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_LDADD) $(LIBS)
 src/tools/linux/symupload/sym_upload.$(OBJEXT):  \
 	src/tools/linux/symupload/$(am__dirstamp) \
 	src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
 src/tools/linux/symupload/sym_upload$(EXEEXT): $(src_tools_linux_symupload_sym_upload_OBJECTS) $(src_tools_linux_symupload_sym_upload_DEPENDENCIES) src/tools/linux/symupload/$(am__dirstamp)
 	@rm -f src/tools/linux/symupload/sym_upload$(EXEEXT)
-	$(src_tools_linux_symupload_sym_upload_LINK) $(src_tools_linux_symupload_sym_upload_OBJECTS) $(src_tools_linux_symupload_sym_upload_LDADD) $(LIBS)
+	$(CXXLINK) $(src_tools_linux_symupload_sym_upload_OBJECTS) $(src_tools_linux_symupload_sym_upload_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
 	-rm -f src/client/linux/crash_generation/crash_generation_client.$(OBJEXT)
 	-rm -f src/client/linux/handler/exception_handler.$(OBJEXT)
 	-rm -f src/client/linux/handler/src_client_linux_linux_client_unittest-exception_handler_unittest.$(OBJEXT)
+	-rm -f src/client/linux/log/log.$(OBJEXT)
 	-rm -f src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT)
 	-rm -f src/client/linux/minidump_writer/linux_dumper.$(OBJEXT)
 	-rm -f src/client/linux/minidump_writer/linux_ptrace_dumper.$(OBJEXT)
@@ -3107,6 +3129,7 @@
 	-rm -f src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-linux_core_dumper_unittest.$(OBJEXT)
 	-rm -f src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-linux_ptrace_dumper_unittest.$(OBJEXT)
 	-rm -f src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest.$(OBJEXT)
+	-rm -f src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.$(OBJEXT)
 	-rm -f src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.$(OBJEXT)
 	-rm -f src/client/minidump_file_writer.$(OBJEXT)
 	-rm -f src/common/convert_UTF.$(OBJEXT)
@@ -3319,6 +3342,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/crash_generation/$(DEPDIR)/crash_generation_client.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/exception_handler.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest-exception_handler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/log/$(DEPDIR)/log.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_core_dumper.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_dumper.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_ptrace_dumper.Po@am__quote@
@@ -3328,6 +3352,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-linux_core_dumper_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-linux_ptrace_dumper_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/convert_UTF.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/dwarf_cfi_to_module.Po@am__quote@
@@ -3648,6 +3673,20 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest.cc'; fi`
 
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.o: src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.o `test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+@am__fastdepCXX_TRUE@	$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.o `test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.obj: src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest-minidump_writer_unittest_utils.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; fi`
+
 src/common/linux/src_client_linux_linux_client_unittest-linux_libc_support_unittest.o: src/common/linux/linux_libc_support_unittest.cc
 @am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_client_linux_linux_client_unittest-linux_libc_support_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest-linux_libc_support_unittest.Tpo -c -o src/common/linux/src_client_linux_linux_client_unittest-linux_libc_support_unittest.o `test -f 'src/common/linux/linux_libc_support_unittest.cc' || echo '$(srcdir)/'`src/common/linux/linux_libc_support_unittest.cc
 @am__fastdepCXX_TRUE@	$(am__mv) src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest-linux_libc_support_unittest.Tpo src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest-linux_libc_support_unittest.Po
@@ -5817,6 +5856,8 @@
 	-rm -f src/client/linux/crash_generation/$(am__dirstamp)
 	-rm -f src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/client/linux/handler/$(am__dirstamp)
+	-rm -f src/client/linux/log/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/client/linux/log/$(am__dirstamp)
 	-rm -f src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/client/linux/minidump_writer/$(am__dirstamp)
 	-rm -f src/common/$(DEPDIR)/$(am__dirstamp)
@@ -5857,7 +5898,7 @@
 
 distclean: distclean-am
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-	-rm -rf src/client/$(DEPDIR) src/client/linux/crash_generation/$(DEPDIR) src/client/linux/handler/$(DEPDIR) src/client/linux/minidump_writer/$(DEPDIR) src/common/$(DEPDIR) src/common/dwarf/$(DEPDIR) src/common/linux/$(DEPDIR) src/common/linux/tests/$(DEPDIR) src/common/tests/$(DEPDIR) src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(DEPDIR) src/tools/linux/core2md/$(DEPDIR) src/tools/linux/dump_syms/$(DEPDIR) src/tools/linux/md2core/$(DEPDIR) src/tools/linux/symupload/$(DEPDIR)
+	-rm -rf src/client/$(DEPDIR) src/client/linux/crash_generation/$(DEPDIR) src/client/linux/handler/$(DEPDIR) src/client/linux/log/$(DEPDIR) src/client/linux/minidump_writer/$(DEPDIR) src/common/$(DEPDIR) src/common/dwarf/$(DEPDIR) src/common/linux/$(DEPDIR) src/common/linux/tests/$(DEPDIR) src/common/tests/$(DEPDIR) src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(DEPDIR) src/tools/linux/core2md/$(DEPDIR) src/tools/linux/dump_syms/$(DEPDIR) src/tools/linux/md2core/$(DEPDIR) src/tools/linux/symupload/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-tags
@@ -5905,7 +5946,7 @@
 maintainer-clean: maintainer-clean-am
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -rf $(top_srcdir)/autom4te.cache
-	-rm -rf src/client/$(DEPDIR) src/client/linux/crash_generation/$(DEPDIR) src/client/linux/handler/$(DEPDIR) src/client/linux/minidump_writer/$(DEPDIR) src/common/$(DEPDIR) src/common/dwarf/$(DEPDIR) src/common/linux/$(DEPDIR) src/common/linux/tests/$(DEPDIR) src/common/tests/$(DEPDIR) src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(DEPDIR) src/tools/linux/core2md/$(DEPDIR) src/tools/linux/dump_syms/$(DEPDIR) src/tools/linux/md2core/$(DEPDIR) src/tools/linux/symupload/$(DEPDIR)
+	-rm -rf src/client/$(DEPDIR) src/client/linux/crash_generation/$(DEPDIR) src/client/linux/handler/$(DEPDIR) src/client/linux/log/$(DEPDIR) src/client/linux/minidump_writer/$(DEPDIR) src/common/$(DEPDIR) src/common/dwarf/$(DEPDIR) src/common/linux/$(DEPDIR) src/common/linux/tests/$(DEPDIR) src/common/tests/$(DEPDIR) src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(DEPDIR) src/tools/linux/core2md/$(DEPDIR) src/tools/linux/dump_syms/$(DEPDIR) src/tools/linux/md2core/$(DEPDIR) src/tools/linux/symupload/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
diff --git a/autotools/config.guess b/autotools/config.guess
index 396482d..aa04f04 100755
--- a/autotools/config.guess
+++ b/autotools/config.guess
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-#   Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011, 2012 Free Software Foundation, Inc.
 
-timestamp='2006-07-02'
+timestamp='2012-06-17'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -17,9 +17,7 @@
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -27,16 +25,16 @@
 # the same distribution terms that you use for the rest of that program.
 
 
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>.  Submit a context
-# diff and a properly formatted ChangeLog entry.
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
 #
 # This script attempts to guess a canonical system name similar to
 # config.sub.  If it succeeds, it prints the system name on stdout, and
 # exits with 0.  Otherwise, it exits with 1.
 #
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
 
 me=`echo "$0" | sed -e 's,.*/,,'`
 
@@ -56,7 +54,8 @@
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -144,7 +143,7 @@
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:NetBSD:*:*)
 	# NetBSD (nbsd) targets should (where applicable) match one or
-	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
 	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
 	# switched to ELF, *-*-netbsd* would select the old
 	# object file format.  This provides both forward
@@ -161,6 +160,7 @@
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
@@ -169,7 +169,7 @@
 	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
 		eval $set_cc_for_build
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
-			| grep __ELF__ >/dev/null
+			| grep -q __ELF__
 		then
 		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
 		    # Return netbsd for either.  FIX?
@@ -179,7 +179,7 @@
 		fi
 		;;
 	    *)
-	        os=netbsd
+		os=netbsd
 		;;
 	esac
 	# The OS release
@@ -200,6 +200,10 @@
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
 	echo "${machine}-${os}${release}"
 	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
     *:OpenBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
 	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
@@ -222,7 +226,7 @@
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
 		;;
 	*5.*)
-	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
 		;;
 	esac
 	# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -268,7 +272,10 @@
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
 	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit ;;
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# Should we change UNAME_MACHINE based on the output of uname instead
@@ -294,7 +301,7 @@
 	echo s390-ibm-zvmoe
 	exit ;;
     *:OS400:*:*)
-        echo powerpc-ibm-os400
+	echo powerpc-ibm-os400
 	exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
@@ -323,14 +330,33 @@
 	case `/usr/bin/uname -p` in
 	    sparc) echo sparc-icl-nx7; exit ;;
 	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
     sun4H:SunOS:5.*:*)
 	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
 	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
-    i86pc:SunOS:5.*:*)
-	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4*:SunOS:6*:*)
 	# According to config.sub, this is the proper way to canonicalize
@@ -374,23 +400,23 @@
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
 	echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+	exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
     m68k:machten:*:*)
 	echo m68k-apple-machten${UNAME_RELEASE}
 	exit ;;
@@ -460,8 +486,8 @@
 	echo m88k-motorola-sysv3
 	exit ;;
     AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
 	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
 	then
 	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -474,7 +500,7 @@
 	else
 	    echo i586-dg-dgux${UNAME_RELEASE}
 	fi
- 	exit ;;
+	exit ;;
     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
 	echo m88k-dolphin-sysv3
 	exit ;;
@@ -531,7 +557,7 @@
 		echo rs6000-ibm-aix3.2
 	fi
 	exit ;;
-    *:AIX:*:[45])
+    *:AIX:*:[4567])
 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
@@ -574,52 +600,52 @@
 	    9000/[678][0-9][0-9])
 		if [ -x /usr/bin/getconf ]; then
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                    case "${sc_cpu_version}" in
-                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-                      532)                      # CPU_PA_RISC2_0
-                        case "${sc_kernel_bits}" in
-                          32) HP_ARCH="hppa2.0n" ;;
-                          64) HP_ARCH="hppa2.0w" ;;
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
 			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
-                        esac ;;
-                    esac
+			esac ;;
+		    esac
 		fi
 		if [ "${HP_ARCH}" = "" ]; then
 		    eval $set_cc_for_build
-		    sed 's/^              //' << EOF >$dummy.c
+		    sed 's/^		//' << EOF >$dummy.c
 
-              #define _HPUX_SOURCE
-              #include <stdlib.h>
-              #include <unistd.h>
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
 
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
 
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
 EOF
 		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -639,7 +665,7 @@
 	    # => hppa64-hp-hpux11.23
 
 	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
-		grep __LP64__ >/dev/null
+		grep -q __LP64__
 	    then
 		HP_ARCH="hppa2.0w"
 	    else
@@ -710,22 +736,22 @@
 	exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
 	echo c1-convex-bsd
-        exit ;;
+	exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
 	if getsysinfo -f scalar_acc
 	then echo c32-convex-bsd
 	else echo c2-convex-bsd
 	fi
-        exit ;;
+	exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
 	echo c34-convex-bsd
-        exit ;;
+	exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
 	echo c38-convex-bsd
-        exit ;;
+	exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
 	echo c4-convex-bsd
-        exit ;;
+	exit ;;
     CRAY*Y-MP:*:*:*)
 	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
@@ -749,14 +775,14 @@
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit ;;
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
     5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -768,37 +794,48 @@
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit ;;
     *:FreeBSD:*:*)
-	case ${UNAME_MACHINE} in
-	    pc98)
-		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
 	    amd64)
 		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	    *)
-		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	esac
 	exit ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
-    i*:MINGW*:*)
+    *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
+    i*:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
     i*:windows32*:*)
-    	# uname -m includes "-pc" on this system.
-    	echo ${UNAME_MACHINE}-mingw32
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
 	exit ;;
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
-    x86:Interix*:[3456]*)
-	echo i586-pc-interix${UNAME_RELEASE}
-	exit ;;
-    EM64T:Interix*:[3456]*)
-	echo x86_64-unknown-interix${UNAME_RELEASE}
-	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 	echo i${UNAME_MACHINE}-pc-mks
 	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
@@ -828,85 +865,13 @@
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit ;;
-    arm*:Linux:*:*)
+    aarch64:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
-    avr32*:Linux:*:*)
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
-    cris:Linux:*:*)
-	echo cris-axis-linux-gnu
-	exit ;;
-    crisv32:Linux:*:*)
-	echo crisv32-axis-linux-gnu
-	exit ;;
-    frv:Linux:*:*)
-    	echo frv-unknown-linux-gnu
-	exit ;;
-    ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
-	exit ;;
-    m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
-	exit ;;
-    m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
-	exit ;;
-    mips:Linux:*:*)
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#undef CPU
-	#undef mips
-	#undef mipsel
-	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=mipsel
-	#else
-	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=mips
-	#else
-	CPU=
-	#endif
-	#endif
-EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^CPU/{
-		s: ::g
-		p
-	    }'`"
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
-	;;
-    mips64:Linux:*:*)
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#undef CPU
-	#undef mips64
-	#undef mips64el
-	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=mips64el
-	#else
-	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=mips64
-	#else
-	CPU=
-	#endif
-	#endif
-EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^CPU/{
-		s: ::g
-		p
-	    }'`"
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
-	;;
-    or32:Linux:*:*)
-	echo or32-unknown-linux-gnu
-	exit ;;
-    ppc:Linux:*:*)
-	echo powerpc-unknown-linux-gnu
-	exit ;;
-    ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-gnu
-	exit ;;
     alpha:Linux:*:*)
 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
 	  EV5)   UNAME_MACHINE=alphaev5 ;;
@@ -916,11 +881,90 @@
 	  EV6)   UNAME_MACHINE=alphaev6 ;;
 	  EV67)  UNAME_MACHINE=alphaev67 ;;
 	  EV68*) UNAME_MACHINE=alphaev68 ;;
-        esac
-	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
 	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
 	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
 	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	LIBC=gnu
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-gnu
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
@@ -929,14 +973,17 @@
 	  *)    echo hppa-unknown-linux-gnu ;;
 	esac
 	exit ;;
-    parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-gnu
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
 	exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
 	echo ${UNAME_MACHINE}-ibm-linux
 	exit ;;
     sh64*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
     sh*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -944,75 +991,18 @@
     sparc:Linux:*:* | sparc64:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
     vax:Linux:*:*)
 	echo ${UNAME_MACHINE}-dec-linux-gnu
 	exit ;;
     x86_64:Linux:*:*)
-	echo x86_64-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
-    i*86:Linux:*:*)
-	# The BFD linker knows what the default object file format is, so
-	# first see if it will tell us. cd to the root directory to prevent
-	# problems with other programs or directories called `ld' in the path.
-	# Set LC_ALL=C to ensure ld outputs messages in English.
-	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
-			 | sed -ne '/supported targets:/!d
-				    s/[ 	][ 	]*/ /g
-				    s/.*supported targets: *//
-				    s/ .*//
-				    p'`
-        case "$ld_supported_targets" in
-	  elf32-i386)
-		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
-		;;
-	  a.out-i386-linux)
-		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
-		exit ;;
-	  coff-i386)
-		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
-		exit ;;
-	  "")
-		# Either a pre-BFD a.out linker (linux-gnuoldld) or
-		# one that does not give us useful --help.
-		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
-		exit ;;
-	esac
-	# Determine whether the default compiler is a.out or elf
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#include <features.h>
-	#ifdef __ELF__
-	# ifdef __GLIBC__
-	#  if __GLIBC__ >= 2
-	LIBC=gnu
-	#  else
-	LIBC=gnulibc1
-	#  endif
-	# else
-	LIBC=gnulibc1
-	# endif
-	#else
-	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-	LIBC=gnu
-	#else
-	LIBC=gnuaout
-	#endif
-	#endif
-	#ifdef __dietlibc__
-	LIBC=dietlibc
-	#endif
-EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^LIBC/{
-		s: ::g
-		p
-	    }'`"
-	test x"${LIBC}" != x && {
-		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
-		exit
-	}
-	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
-	;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
 	# earlier versions are messed up and put the nodename in both
@@ -1020,11 +1010,11 @@
 	echo i386-sequent-sysv4
 	exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
 	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
+	# Use sysv4.2uw... so that sysv4* matches it.
 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 	exit ;;
     i*86:OS/2:*:*)
@@ -1041,7 +1031,7 @@
     i*86:syllable:*:*)
 	echo ${UNAME_MACHINE}-pc-syllable
 	exit ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
 	echo i386-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
     i*86:*DOS:*:*)
@@ -1056,7 +1046,7 @@
 	fi
 	exit ;;
     i*86:*:5:[678]*)
-    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
 	case `/bin/uname -X | grep "^Machine"` in
 	    *486*)	     UNAME_MACHINE=i486 ;;
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
@@ -1084,10 +1074,13 @@
 	exit ;;
     pc:*:*:*)
 	# Left here for compatibility:
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i386.
-	echo i386-pc-msdosdjgpp
-        exit ;;
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
     Intel:Mach:3*:*)
 	echo i386-pc-mach3
 	exit ;;
@@ -1122,8 +1115,18 @@
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
 	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && { echo i486-ncr-sysv4; exit; } ;;
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
 	echo m68k-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
@@ -1136,7 +1139,7 @@
     rs6000:LynxOS:2.*:*)
 	echo rs6000-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
-    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
 	echo powerpc-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
     SM[BE]S:UNIX_SV:*:*)
@@ -1156,10 +1159,10 @@
 		echo ns32k-sni-sysv
 	fi
 	exit ;;
-    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                      # says <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes@openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
@@ -1185,11 +1188,11 @@
 	exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
 	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
+		echo mips-nec-sysv${UNAME_RELEASE}
 	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
+		echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
-        exit ;;
+	exit ;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
 	echo powerpc-be-beos
 	exit ;;
@@ -1199,6 +1202,9 @@
     BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
 	echo i586-pc-beos
 	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
     SX-4:SUPER-UX:*:*)
 	echo sx4-nec-superux${UNAME_RELEASE}
 	exit ;;
@@ -1208,6 +1214,15 @@
     SX-6:SUPER-UX:*:*)
 	echo sx6-nec-superux${UNAME_RELEASE}
 	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
     Power*:Rhapsody:*:*)
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	exit ;;
@@ -1217,6 +1232,16 @@
     *:Darwin:*:*)
 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
 	case $UNAME_PROCESSOR in
+	    i386)
+		eval $set_cc_for_build
+		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		      grep IS_64BIT_ARCH >/dev/null
+		  then
+		      UNAME_PROCESSOR="x86_64"
+		  fi
+		fi ;;
 	    unknown) UNAME_PROCESSOR=powerpc ;;
 	esac
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
@@ -1232,7 +1257,10 @@
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
 	echo nse-tandem-nsk${UNAME_RELEASE}
 	exit ;;
     NSR-?:NONSTOP_KERNEL:*:*)
@@ -1277,13 +1305,13 @@
 	echo pdp10-unknown-its
 	exit ;;
     SEI:*:*:SEIUX)
-        echo mips-sei-seiux${UNAME_RELEASE}
+	echo mips-sei-seiux${UNAME_RELEASE}
 	exit ;;
     *:DragonFly:*:*)
 	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit ;;
     *:*VMS:*:*)
-    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
 	case "${UNAME_MACHINE}" in
 	    A*) echo alpha-dec-vms ; exit ;;
 	    I*) echo ia64-dec-vms ; exit ;;
@@ -1298,6 +1326,12 @@
     i*86:rdos:*:*)
 	echo ${UNAME_MACHINE}-pc-rdos
 	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1320,11 +1354,11 @@
 #include <sys/param.h>
   printf ("m68k-sony-newsos%s\n",
 #ifdef NEWSOS4
-          "4"
+	"4"
 #else
-	  ""
+	""
 #endif
-         ); exit (0);
+	); exit (0);
 #endif
 #endif
 
@@ -1458,9 +1492,9 @@
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
 and
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
 
 If the version you run ($0) is already up to date, please
 send the following data and any information you think might be
diff --git a/autotools/config.sub b/autotools/config.sub
index fab0aa3..aa2cf19 100755
--- a/autotools/config.sub
+++ b/autotools/config.sub
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-#   Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011, 2012 Free Software Foundation, Inc.
 
-timestamp='2006-09-20'
+timestamp='2012-06-17'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -21,9 +21,7 @@
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -32,13 +30,16 @@
 
 
 # Please send patches to <config-patches@gnu.org>.  Submit a context
-# diff and a properly formatted ChangeLog entry.
+# diff and a properly formatted GNU ChangeLog entry.
 #
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
 # If it is invalid, we print an error message on stderr and exit with code 1.
 # Otherwise, we print the canonical config type on stdout and succeed.
 
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
 # that are meaningful with *any* GNU software.
@@ -72,7 +73,8 @@
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -120,12 +122,18 @@
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
-  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
   *)
     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     if [ $basic_machine != $1 ]
@@ -148,10 +156,13 @@
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray)
+	-apple | -axis | -knuth | -cray | -microblaze)
 		os=
 		basic_machine=$1
 		;;
+	-bluegene*)
+		os=-cnk
+		;;
 	-sim | -cisco | -oki | -wec | -winbond)
 		os=
 		basic_machine=$1
@@ -166,10 +177,10 @@
 		os=-chorusos
 		basic_machine=$1
 		;;
- 	-chorusrdb)
- 		os=-chorusrdb
+	-chorusrdb)
+		os=-chorusrdb
 		basic_machine=$1
- 		;;
+		;;
 	-hiux*)
 		os=-hiuxwe2
 		;;
@@ -214,6 +225,12 @@
 	-isc*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
 	-lynx*)
 		os=-lynxos
 		;;
@@ -238,24 +255,32 @@
 	# Some are omitted here because they have special meanings below.
 	1750a | 580 \
 	| a29k \
+	| aarch64 | aarch64_be \
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
 	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+        | be32 | be64 \
 	| bfin \
 	| c4x | clipper \
 	| d10v | d30v | dlx | dsp16xx \
-	| fr30 | frv \
+	| epiphany \
+	| fido | fr30 | frv \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
+	| le32 | le64 \
+	| lm32 \
 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | mcore \
+	| maxq | mb | microblaze | mcore | mep | metag \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
-	| mips64vr | mips64vrel \
+	| mips64octeon | mips64octeonel \
 	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
 	| mips64vr4100 | mips64vr4100el \
 	| mips64vr4300 | mips64vr4300el \
 	| mips64vr5000 | mips64vr5000el \
@@ -268,29 +293,42 @@
 	| mipsisa64sr71k | mipsisa64sr71kel \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
+	| moxie \
 	| mt \
 	| msp430 \
+	| nds32 | nds32le | nds32be \
 	| nios | nios2 \
 	| ns16k | ns32k \
+	| open8 \
 	| or32 \
 	| pdp10 | pdp11 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
+	| rl78 | rx \
 	| score \
-	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu | strongarm \
-	| tahoe | thumb | tic4x | tic80 | tron \
-	| v850 | v850e \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
 	| we32k \
-	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
-	| z8k)
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
 		basic_machine=$basic_machine-unknown
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12)
-		# Motorola 68HC11/12.
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
 		basic_machine=$basic_machine-unknown
 		os=-none
 		;;
@@ -300,6 +338,21 @@
 		basic_machine=mt-unknown
 		;;
 
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
@@ -314,29 +367,36 @@
 	# Recognize the basic CPU types with company name.
 	580-* \
 	| a29k-* \
+	| aarch64-* | aarch64_be-* \
 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
+	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
 	| clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
-	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
+	| le32-* | le64-* \
+	| lm32-* \
 	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
-	| mips64vr-* | mips64vrel-* \
+	| mips64octeon-* | mips64octeonel-* \
 	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
 	| mips64vr4100-* | mips64vr4100el-* \
 	| mips64vr4300-* | mips64vr4300el-* \
 	| mips64vr5000-* | mips64vr5000el-* \
@@ -351,27 +411,36 @@
 	| mmix-* \
 	| mt-* \
 	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
 	| nios-* | nios2-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
 	| pyramid-* \
-	| romp-* | rs6000-* \
-	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
-	| tahoe-* | thumb-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
 	| tron-* \
-	| v850-* | v850e-* | vax-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
-	| xstormy16-* | xtensa-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
 	| ymp-* \
-	| z8k-*)
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
 		;;
 	# Recognize the various machine names and aliases which stand
 	# for a CPU type and a company and sometimes even an OS.
@@ -389,7 +458,7 @@
 		basic_machine=a29k-amd
 		os=-udi
 		;;
-    	abacus)
+	abacus)
 		basic_machine=abacus-unknown
 		;;
 	adobe68k)
@@ -435,6 +504,10 @@
 		basic_machine=m68k-apollo
 		os=-bsd
 		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
 	aux)
 		basic_machine=m68k-apple
 		os=-aux
@@ -443,10 +516,35 @@
 		basic_machine=ns32k-sequent
 		os=-dynix
 		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	c90)
 		basic_machine=c90-cray
 		os=-unicos
 		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
 	convex-c1)
 		basic_machine=c1-convex
 		os=-bsd
@@ -475,8 +573,8 @@
 		basic_machine=craynv-cray
 		os=-unicosmp
 		;;
-	cr16c)
-		basic_machine=cr16c-unknown
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
 		os=-elf
 		;;
 	crds | unos)
@@ -514,6 +612,10 @@
 		basic_machine=m88k-motorola
 		os=-sysv3
 		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
 	djgpp)
 		basic_machine=i586-pc
 		os=-msdosdjgpp
@@ -629,7 +731,6 @@
 	i370-ibm* | ibm*)
 		basic_machine=i370-ibm
 		;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
 	i*86v32)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv32
@@ -668,6 +769,14 @@
 		basic_machine=m68k-isi
 		os=-sysv
 		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
 	m88k-omron*)
 		basic_machine=m88k-omron
 		;;
@@ -679,10 +788,17 @@
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
+	microblaze)
+		basic_machine=microblaze-xilinx
+		;;
 	mingw32)
 		basic_machine=i386-pc
 		os=-mingw32
 		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
 	miniframe)
 		basic_machine=m68000-convergent
 		;;
@@ -711,10 +827,18 @@
 	ms1-*)
 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 		;;
+	msys)
+		basic_machine=i386-pc
+		os=-msys
+		;;
 	mvs)
 		basic_machine=i370-ibm
 		os=-mvs
 		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
 	ncr3000)
 		basic_machine=i486-ncr
 		os=-sysv4
@@ -779,6 +903,12 @@
 	np1)
 		basic_machine=np1-gould
 		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
@@ -809,6 +939,14 @@
 		basic_machine=i860-intel
 		os=-osf
 		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
 	pbd)
 		basic_machine=sparc-tti
 		;;
@@ -853,9 +991,10 @@
 		;;
 	power)	basic_machine=power-ibm
 		;;
-	ppc)	basic_machine=powerpc-unknown
+	ppc | ppcbe)	basic_machine=powerpc-unknown
 		;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppcle | powerpclittle | ppc-le | powerpc-little)
 		basic_machine=powerpcle-unknown
@@ -925,6 +1064,9 @@
 		basic_machine=sh-hitachi
 		os=-hms
 		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
 	sh64)
 		basic_machine=sh64-unknown
 		;;
@@ -946,6 +1088,9 @@
 		basic_machine=i860-stratus
 		os=-sysv4
 		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	sun2)
 		basic_machine=m68000-sun
 		;;
@@ -1002,17 +1147,9 @@
 		basic_machine=t90-cray
 		os=-unicos
 		;;
-	tic54x | c54x*)
-		basic_machine=tic54x-unknown
-		os=-coff
-		;;
-	tic55x | c55x*)
-		basic_machine=tic55x-unknown
-		os=-coff
-		;;
-	tic6x | c6x*)
-		basic_machine=tic6x-unknown
-		os=-coff
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
 		;;
 	tx39)
 		basic_machine=mipstx39-unknown
@@ -1081,6 +1218,9 @@
 	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
 	ymp)
 		basic_machine=ymp-cray
 		os=-unicos
@@ -1089,6 +1229,10 @@
 		basic_machine=z8k-unknown
 		os=-sim
 		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
 	none)
 		basic_machine=none-none
 		os=-none
@@ -1127,7 +1271,7 @@
 	we32k)
 		basic_machine=we32k-att
 		;;
-	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
 		basic_machine=sh-unknown
 		;;
 	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1174,9 +1318,12 @@
 if [ x"$os" != x"" ]
 then
 case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
+	# First match some system type aliases
+	# that might get confused with valid system types.
 	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
 	-solaris1 | -solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
 		;;
@@ -1197,21 +1344,23 @@
 	# Each alternative MUST END IN A *, to match a version number.
 	# -sysv* is not here because it comes later, after sysvr4.
 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
-	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
-	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* \
+	      | -aos* | -aros* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -chorusos* | -chorusrdb* \
-	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1219,7 +1368,7 @@
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1258,7 +1407,7 @@
 	-opened*)
 		os=-openedition
 		;;
-        -os400*)
+	-os400*)
 		os=-os400
 		;;
 	-wince*)
@@ -1307,7 +1456,7 @@
 	-sinix*)
 		os=-sysv4
 		;;
-        -tpf*)
+	-tpf*)
 		os=-tpf
 		;;
 	-triton*)
@@ -1349,6 +1498,11 @@
 	-zvmoe)
 		os=-zvmoe
 		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
 	-none)
 		;;
 	*)
@@ -1371,10 +1525,10 @@
 # system, and we'll never get to this point.
 
 case $basic_machine in
-        score-*)
+	score-*)
 		os=-elf
 		;;
-        spu-*)
+	spu-*)
 		os=-elf
 		;;
 	*-acorn)
@@ -1386,8 +1540,20 @@
 	arm*-semi)
 		os=-aout
 		;;
-        c4x-* | tic4x-*)
-        	os=-coff
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
 		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
@@ -1407,13 +1573,13 @@
 		;;
 	m68000-sun)
 		os=-sunos3
-		# This also exists in the configure program, but was not the
-		# default.
-		# os=-sunos4
 		;;
 	m68*-cisco)
 		os=-aout
 		;;
+	mep-*)
+		os=-elf
+		;;
 	mips*-cisco)
 		os=-elf
 		;;
@@ -1438,7 +1604,7 @@
 	*-ibm)
 		os=-aix
 		;;
-    	*-knuth)
+	*-knuth)
 		os=-mmixware
 		;;
 	*-wec)
@@ -1543,7 +1709,7 @@
 			-sunos*)
 				vendor=sun
 				;;
-			-aix*)
+			-cnk*|-aix*)
 				vendor=ibm
 				;;
 			-beos*)
diff --git a/configure b/configure
index 9939abc..5a432c8 100755
--- a/configure
+++ b/configure
@@ -616,6 +616,8 @@
 ax_pthread_config
 EGREP
 GREP
+GCC_FALSE
+GCC_TRUE
 RANLIB
 am__fastdepCXX_FALSE
 am__fastdepCXX_TRUE
@@ -4506,6 +4508,14 @@
   RANLIB="$ac_cv_prog_RANLIB"
 fi
 
+ if test "$GCC" = yes; then
+  GCC_TRUE=
+  GCC_FALSE='#'
+else
+  GCC_TRUE='#'
+  GCC_FALSE=
+fi
+   # let the Makefile know if we're gcc
 
 
 
@@ -5523,6 +5533,10 @@
   as_fn_error "conditional \"am__fastdepCXX\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${GCC_TRUE}" && test -z "${GCC_FALSE}"; then
+  as_fn_error "conditional \"GCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${LINUX_HOST_TRUE}" && test -z "${LINUX_HOST_FALSE}"; then
   as_fn_error "conditional \"LINUX_HOST\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/configure.ac b/configure.ac
index 26aec59..b3c8a0e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,7 @@
 AC_PROG_CPP
 AC_PROG_CXX
 AC_PROG_RANLIB
+AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
 
 AC_HEADER_STDC
 m4_include(m4/ax_pthread.m4)
diff --git a/src/client/ios/handler/ios_exception_minidump_generator.mm b/src/client/ios/handler/ios_exception_minidump_generator.mm
index cd0fe65..b8aebc2 100644
--- a/src/client/ios/handler/ios_exception_minidump_generator.mm
+++ b/src/client/ios/handler/ios_exception_minidump_generator.mm
@@ -40,12 +40,14 @@
 const int kExceptionType = EXC_SOFTWARE;
 const int kExceptionCode = MD_EXCEPTION_CODE_MAC_NS_EXCEPTION;
 
+#ifdef HAS_ARM_SUPPORT
 // Append the given 4 bytes value to the sp position of the stack represented
 // by memory.
 void AppendToMemory(uint8_t *memory, uint32_t sp, uint32_t data) {
   assert(sizeof(data) == 4);
   memcpy(memory + sp, &data, sizeof(data));
 }
+#endif
 
 }  // namespace
 
diff --git a/src/client/linux/android_link.h b/src/client/linux/android_link.h
index 430ac3b..32261fc 100644
--- a/src/client/linux/android_link.h
+++ b/src/client/linux/android_link.h
@@ -33,7 +33,11 @@
 #ifndef GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_LINK_H_
 #define GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_LINK_H_
 
-#include <sys/exec_elf.h>
+// TODO(zhenghao): exec_elf.h conflicts with linux/elf.h.
+// But we still need ELFSIZE.
+//#include <sys/exec_elf.h>
+#include <machine/exec.h>
+#define ELFSIZE ARCH_ELFSIZE
 
 #ifndef ElfW
 #define ElfW(type)	_ElfW (Elf, ELFSIZE, type)
diff --git a/src/client/linux/android_ucontext.h b/src/client/linux/android_ucontext.h
index 30a4e6c..7942db7 100644
--- a/src/client/linux/android_ucontext.h
+++ b/src/client/linux/android_ucontext.h
@@ -35,33 +35,15 @@
 #ifndef GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
 #define GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
 
+#include <android/api-level.h>
 #include <signal.h>
 
-#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
+// <signal.h> didn't include <asm/sigcontext.h> before API level 8.
+// It is used to define struct sigcontext properly.
+#if defined(__arm__) && __ANDROID_API__ < 8
+#include <asm/sigcontext.h>
+#endif
 
-struct sigcontext {
-  uint32_t trap_no;
-  uint32_t error_code;
-  uint32_t oldmask;
-  uint32_t arm_r0;
-  uint32_t arm_r1;
-  uint32_t arm_r2;
-  uint32_t arm_r3;
-  uint32_t arm_r4;
-  uint32_t arm_r5;
-  uint32_t arm_r6;
-  uint32_t arm_r7;
-  uint32_t arm_r8;
-  uint32_t arm_r9;
-  uint32_t arm_r10;
-  uint32_t arm_fp;
-  uint32_t arm_ip;
-  uint32_t arm_sp;
-  uint32_t arm_lr;
-  uint32_t arm_pc;
-  uint32_t arm_cpsr;
-  uint32_t fault_address;
-};
 typedef uint32_t __sigset_t;
 typedef struct sigcontext mcontext_t;
 typedef struct ucontext {
@@ -72,6 +54,4 @@
   __sigset_t uc_sigmask;
 } ucontext_t;
 
-#endif
-
 #endif  // GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
diff --git a/src/client/linux/crash_generation/crash_generation_server.cc b/src/client/linux/crash_generation/crash_generation_server.cc
index 76c9d9c..f7e7244 100644
--- a/src/client/linux/crash_generation/crash_generation_server.cc
+++ b/src/client/linux/crash_generation/crash_generation_server.cc
@@ -170,7 +170,7 @@
   OnClientExitingCallback exit_callback,
   void* exit_context,
   bool generate_dumps,
-  const std::string* dump_path) :
+  const string* dump_path) :
     server_fd_(listen_fd),
     dump_callback_(dump_callback),
     dump_context_(dump_context),
@@ -384,7 +384,7 @@
     return true;
   }
 
-  std::string minidump_filename;
+  string minidump_filename;
   if (!MakeMinidumpFilename(minidump_filename))
     return true;
 
@@ -440,7 +440,7 @@
 }
 
 bool
-CrashGenerationServer::MakeMinidumpFilename(std::string& outFilename)
+CrashGenerationServer::MakeMinidumpFilename(string& outFilename)
 {
   GUID guid;
   char guidString[kGUIDStringLength+1];
diff --git a/src/client/linux/crash_generation/crash_generation_server.h b/src/client/linux/crash_generation/crash_generation_server.h
index a9dc1f7..483fb70 100644
--- a/src/client/linux/crash_generation/crash_generation_server.h
+++ b/src/client/linux/crash_generation/crash_generation_server.h
@@ -34,6 +34,8 @@
 
 #include <string>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
 class ClientInfo;
@@ -45,7 +47,7 @@
   // be thread safe.
   typedef void (*OnClientDumpRequestCallback)(void* context,
                                               const ClientInfo* client_info,
-                                              const std::string* file_path);
+                                              const string* file_path);
 
   typedef void (*OnClientExitingCallback)(void* context,
                                           const ClientInfo* client_info);
@@ -69,7 +71,7 @@
                         OnClientExitingCallback exit_callback,
                         void* exit_context,
                         bool generate_dumps,
-                        const std::string* dump_path);
+                        const string* dump_path);
 
   ~CrashGenerationServer();
 
@@ -100,7 +102,7 @@
   bool ControlEvent(short revents);
 
   // Return a unique filename at which a minidump can be written
-  bool MakeMinidumpFilename(std::string& outFilename);
+  bool MakeMinidumpFilename(string& outFilename);
 
   // Trampoline to |Run()|
   static void* ThreadMain(void* arg);
@@ -115,7 +117,7 @@
 
   bool generate_dumps_;
 
-  std::string dump_dir_;
+  string dump_dir_;
 
   bool started_;
 
diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc
index fff2d1c..f505ff3 100644
--- a/src/client/linux/handler/exception_handler.cc
+++ b/src/client/linux/handler/exception_handler.cc
@@ -90,6 +90,7 @@
 
 #include "common/linux/linux_libc_support.h"
 #include "common/memory.h"
+#include "client/linux/log/log.h"
 #include "client/linux/minidump_writer/linux_dumper.h"
 #include "client/linux/minidump_writer/minidump_writer.h"
 #include "common/linux/guid_creator.h"
@@ -125,7 +126,7 @@
     PTHREAD_MUTEX_INITIALIZER;
 
 // Runs before crashing: normal context.
-ExceptionHandler::ExceptionHandler(const std::string &dump_path,
+ExceptionHandler::ExceptionHandler(const string &dump_path,
                                    FilterCallback filter,
                                    MinidumpCallback callback,
                                    void *callback_context,
@@ -138,7 +139,7 @@
   Init(dump_path, -1);
 }
 
-ExceptionHandler::ExceptionHandler(const std::string &dump_path,
+ExceptionHandler::ExceptionHandler(const string &dump_path,
                                    FilterCallback filter,
                                    MinidumpCallback callback,
                                    void* callback_context,
@@ -157,7 +158,7 @@
   UninstallHandlers();
 }
 
-void ExceptionHandler::Init(const std::string &dump_path,
+void ExceptionHandler::Init(const string &dump_path,
                             const int server_fd)
 {
   crash_handler_ = NULL;
@@ -391,14 +392,15 @@
     // is the write() and read() calls will fail with EBADF
     static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump \
                                        sys_pipe failed:";
-    sys_write(2, no_pipe_msg, sizeof(no_pipe_msg) - 1);
-    sys_write(2, strerror(errno), strlen(strerror(errno)));
-    sys_write(2, "\n", 1);
+    logger::write(no_pipe_msg, sizeof(no_pipe_msg) - 1);
+    logger::write(strerror(errno), strlen(strerror(errno)));
+    logger::write("\n", 1);
   }
 
   const pid_t child = sys_clone(
       ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
       &thread_arg, NULL, NULL, NULL);
+
   int r, status;
   // Allow the child to ptrace us
   sys_prctl(PR_SET_PTRACER, child);
@@ -412,9 +414,9 @@
 
   if (r == -1) {
     static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:";
-    sys_write(2, msg, sizeof(msg) - 1);
-    sys_write(2, strerror(errno), strlen(strerror(errno)));
-    sys_write(2, "\n", 1);
+    logger::write(msg, sizeof(msg) - 1);
+    logger::write(strerror(errno), strlen(strerror(errno)));
+    logger::write("\n", 1);
   }
 
   bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;
@@ -434,9 +436,9 @@
   if(r == -1) {
     static const char msg[] = "ExceptionHandler::SendContinueSignalToChild \
                                sys_write failed:";
-    sys_write(2, msg, sizeof(msg) - 1);
-    sys_write(2, strerror(errno), strlen(strerror(errno)));
-    sys_write(2, "\n", 1);
+    logger::write(msg, sizeof(msg) - 1);
+    logger::write(strerror(errno), strlen(strerror(errno)));
+    logger::write("\n", 1);
   }
 }
 
@@ -449,9 +451,9 @@
   if(r == -1) {
     static const char msg[] = "ExceptionHandler::WaitForContinueSignal \
                                sys_read failed:";
-    sys_write(2, msg, sizeof(msg) - 1);
-    sys_write(2, strerror(errno), strlen(strerror(errno)));
-    sys_write(2, "\n", 1);
+    logger::write(msg, sizeof(msg) - 1);
+    logger::write(strerror(errno), strlen(strerror(errno)));
+    logger::write("\n", 1);
   }
 }
 
@@ -467,7 +469,7 @@
 }
 
 // static
-bool ExceptionHandler::WriteMinidump(const std::string &dump_path,
+bool ExceptionHandler::WriteMinidump(const string &dump_path,
                                      MinidumpCallback callback,
                                      void* callback_context) {
   ExceptionHandler eh(dump_path, NULL, callback, callback_context, false);
@@ -495,7 +497,7 @@
 #endif  // !defined(__ARM_EABI__)
 }
 
-void ExceptionHandler::AddMappingInfo(const std::string& name,
+void ExceptionHandler::AddMappingInfo(const string& name,
                                       const u_int8_t identifier[sizeof(MDGUID)],
                                       uintptr_t start_address,
                                       size_t mapping_size,
diff --git a/src/client/linux/handler/exception_handler.h b/src/client/linux/handler/exception_handler.h
index 94766eb..4bc8ba7 100644
--- a/src/client/linux/handler/exception_handler.h
+++ b/src/client/linux/handler/exception_handler.h
@@ -43,6 +43,7 @@
 #endif
 #include "client/linux/crash_generation/crash_generation_client.h"
 #include "client/linux/minidump_writer/minidump_writer.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "processor/scoped_ptr.h"
 
@@ -127,7 +128,7 @@
   // 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 std::string &dump_path,
+  ExceptionHandler(const string &dump_path,
                    FilterCallback filter, MinidumpCallback callback,
                    void *callback_context,
                    bool install_handler);
@@ -137,7 +138,7 @@
   // server_fd is invalid, in-process dump generation will be
   // used. See the above ctor for a description of the other
   // parameters.
-  ExceptionHandler(const std::string& dump_path,
+  ExceptionHandler(const string& dump_path,
                    FilterCallback filter, MinidumpCallback callback,
                    void* callback_context,
                    bool install_handler,
@@ -146,8 +147,8 @@
   ~ExceptionHandler();
 
   // Get and set the minidump path.
-  std::string dump_path() const { return dump_path_; }
-  void set_dump_path(const std::string &dump_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();
@@ -163,7 +164,7 @@
 
   // Convenience form of WriteMinidump which does not require an
   // ExceptionHandler instance.
-  static bool WriteMinidump(const std::string &dump_path,
+  static bool WriteMinidump(const string &dump_path,
                             MinidumpCallback callback,
                             void *callback_context);
 
@@ -187,14 +188,14 @@
   // Add information about a memory mapping. This can be used if
   // a custom library loader is used that maps things in a way
   // that the linux dumper can't handle by reading the maps file.
-  void AddMappingInfo(const std::string& name,
+  void AddMappingInfo(const string& name,
                       const u_int8_t identifier[sizeof(MDGUID)],
                       uintptr_t start_address,
                       size_t mapping_size,
                       size_t file_offset);
 
  private:
-  void Init(const std::string &dump_path,
+  void Init(const string &dump_path,
             const int server_fd);
   bool InstallHandlers();
   void UninstallHandlers();
@@ -216,9 +217,9 @@
 
   scoped_ptr<CrashGenerationClient> crash_generation_client_;
 
-  std::string dump_path_;
-  std::string next_minidump_path_;
-  std::string next_minidump_id_;
+  string dump_path_;
+  string next_minidump_path_;
+  string next_minidump_id_;
 
   // Pointers to C-string representations of the above. These are set
   // when the above are set so we can avoid calling c_str during
diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc
index f8024f2..f931472 100644
--- a/src/client/linux/handler/exception_handler_unittest.cc
+++ b/src/client/linux/handler/exception_handler_unittest.cc
@@ -45,6 +45,7 @@
 #include "common/linux/file_id.h"
 #include "common/linux/linux_libc_support.h"
 #include "common/tests/auto_tempdir.h"
+#include "common/using_std_string.h"
 #include "third_party/lss/linux_syscall_support.h"
 #include "google_breakpad/processor/minidump.h"
 
@@ -130,7 +131,7 @@
   filename[len] = 0;
   close(fds[0]);
 
-  const std::string minidump_filename = temp_dir.path() + "/" + filename +
+  const string minidump_filename = temp_dir.path() + "/" + filename +
                                         ".dmp";
 
   struct stat st;
@@ -204,7 +205,7 @@
   filename[len] = 0;
   close(fds[0]);
 
-  const std::string minidump_filename = temp_dir.path() + "/" + filename +
+  const string minidump_filename = temp_dir.path() + "/" + filename +
                                         ".dmp";
 
   struct stat st;
@@ -329,7 +330,7 @@
   filename[len] = 0;
   close(fds[0]);
 
-  const std::string minidump_filename = temp_dir.path() + "/" + filename +
+  const string minidump_filename = temp_dir.path() + "/" + filename +
                                         ".dmp";
 
   struct stat st;
@@ -454,7 +455,7 @@
   filename[len] = 0;
   close(fds[0]);
 
-  const std::string minidump_filename = temp_dir.path() + "/" + filename +
+  const string minidump_filename = temp_dir.path() + "/" + filename +
                                         ".dmp";
 
   struct stat st;
@@ -555,7 +556,7 @@
   filename[len] = 0;
   close(fds[0]);
 
-  const std::string minidump_filename = temp_dir.path() + "/" + filename +
+  const string minidump_filename = temp_dir.path() + "/" + filename +
                                         ".dmp";
 
   struct stat st;
@@ -669,7 +670,14 @@
              void* context) {
   const int fd = (intptr_t) context;
   int fds[2];
-  pipe(fds);
+  if (pipe(fds) == -1) {
+    // There doesn't seem to be any way to reliably handle
+    // this failure without the parent process hanging
+    // At least make sure that this process doesn't access
+    // unexpected file descriptors
+    fds[0] = -1;
+    fds[1] = -1;
+  }
   struct kernel_msghdr msg = {0};
   struct kernel_iovec iov;
   iov.iov_base = const_cast<void*>(crash_context);
@@ -736,6 +744,7 @@
   ASSERT_EQ(n, kCrashContextSize);
   ASSERT_EQ(msg.msg_controllen, kControlMsgSize);
   ASSERT_EQ(msg.msg_flags, 0);
+  ASSERT_EQ(close(fds[0]), 0);
 
   pid_t crashing_pid = -1;
   int signal_fd = -1;
@@ -759,11 +768,12 @@
   ASSERT_NE(signal_fd, -1);
 
   AutoTempDir temp_dir;
-  std::string templ = temp_dir.path() + "/exception-handler-unittest";
+  string templ = temp_dir.path() + "/exception-handler-unittest";
   ASSERT_TRUE(WriteMinidump(templ.c_str(), crashing_pid, context,
                             kCrashContextSize));
   static const char b = 0;
   HANDLE_EINTR(write(signal_fd, &b, 1));
+  ASSERT_EQ(close(signal_fd), 0);
 
   int status;
   ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1);
diff --git a/src/client/linux/log/log.cc b/src/client/linux/log/log.cc
new file mode 100644
index 0000000..1863591
--- /dev/null
+++ b/src/client/linux/log/log.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "client/linux/log/log.h"
+
+#if defined(__ANDROID__)
+#include <android/log.h>
+#else
+#include "third_party/lss/linux_syscall_support.h"
+#endif
+
+namespace logger {
+
+int write(const char* buf, size_t nbytes) {
+#if defined(__ANDROID__)
+  return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
+#else
+  return sys_write(2, buf, nbytes);
+#endif
+}
+
+}  // namespace logger
diff --git a/src/client/linux/log/log.h b/src/client/linux/log/log.h
new file mode 100644
index 0000000..a50e30d
--- /dev/null
+++ b/src/client/linux/log/log.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_LOG_LOG_H_
+#define CLIENT_LINUX_LOG_LOG_H_
+
+#include <stddef.h>
+
+namespace logger {
+
+int write(const char* buf, size_t nbytes);
+
+}  // namespace logger
+
+#endif  // CLIENT_LINUX_LOG_LOG_H_
diff --git a/src/client/linux/minidump_writer/directory_reader_unittest.cc b/src/client/linux/minidump_writer/directory_reader_unittest.cc
index 3034e61..326f9e3 100644
--- a/src/client/linux/minidump_writer/directory_reader_unittest.cc
+++ b/src/client/linux/minidump_writer/directory_reader_unittest.cc
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 
 #include "client/linux/minidump_writer/directory_reader.h"
+#include "common/using_std_string.h"
 #include "breakpad_googletest_includes.h"
 
 using namespace google_breakpad;
@@ -44,7 +45,7 @@
 }
 
 TEST(DirectoryReaderTest, CompareResults) {
-  std::set<std::string> dent_set;
+  std::set<string> dent_set;
 
   DIR *const dir = opendir("/proc/self");
   ASSERT_TRUE(dir != NULL);
diff --git a/src/client/linux/minidump_writer/line_reader_unittest.cc b/src/client/linux/minidump_writer/line_reader_unittest.cc
index a2ea17f..17a5467 100644
--- a/src/client/linux/minidump_writer/line_reader_unittest.cc
+++ b/src/client/linux/minidump_writer/line_reader_unittest.cc
@@ -33,6 +33,7 @@
 
 #include "client/linux/minidump_writer/line_reader.h"
 #include "breakpad_googletest_includes.h"
+#include "common/linux/eintr_wrapper.h"
 
 using namespace google_breakpad;
 
@@ -70,16 +71,17 @@
 
 TEST(LineReaderTest, OneLineTerminated) {
   const int fd = TemporaryFile();
-  write(fd, "a\n", 2);
+  const int r = HANDLE_EINTR(write(fd, "a\n", 2));
+  ASSERT_EQ(2, r);
   lseek(fd, 0, SEEK_SET);
   LineReader reader(fd);
 
   const char *line;
   unsigned int len;
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, (unsigned int)1);
-  ASSERT_EQ(line[0], 'a');
-  ASSERT_EQ(line[1], 0);
+  ASSERT_EQ((unsigned int)1, len);
+  ASSERT_EQ('a', line[0]);
+  ASSERT_EQ('\0', line[1]);
   reader.PopLine(len);
 
   ASSERT_FALSE(reader.GetNextLine(&line, &len));
@@ -89,16 +91,17 @@
 
 TEST(LineReaderTest, OneLine) {
   const int fd = TemporaryFile();
-  write(fd, "a", 1);
+  const int r = HANDLE_EINTR(write(fd, "a", 1));
+  ASSERT_EQ(1, r);
   lseek(fd, 0, SEEK_SET);
   LineReader reader(fd);
 
   const char *line;
   unsigned len;
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, (unsigned)1);
-  ASSERT_EQ(line[0], 'a');
-  ASSERT_EQ(line[1], 0);
+  ASSERT_EQ((unsigned)1, len);
+  ASSERT_EQ('a', line[0]);
+  ASSERT_EQ('\0', line[1]);
   reader.PopLine(len);
 
   ASSERT_FALSE(reader.GetNextLine(&line, &len));
@@ -108,22 +111,23 @@
 
 TEST(LineReaderTest, TwoLinesTerminated) {
   const int fd = TemporaryFile();
-  write(fd, "a\nb\n", 4);
+  const int r = HANDLE_EINTR(write(fd, "a\nb\n", 4));
+  ASSERT_EQ(4, r);
   lseek(fd, 0, SEEK_SET);
   LineReader reader(fd);
 
   const char *line;
   unsigned len;
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, (unsigned)1);
-  ASSERT_EQ(line[0], 'a');
-  ASSERT_EQ(line[1], 0);
+  ASSERT_EQ((unsigned)1, len);
+  ASSERT_EQ('a', line[0]);
+  ASSERT_EQ('\0', line[1]);
   reader.PopLine(len);
 
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, (unsigned)1);
-  ASSERT_EQ(line[0], 'b');
-  ASSERT_EQ(line[1], 0);
+  ASSERT_EQ((unsigned)1, len);
+  ASSERT_EQ('b', line[0]);
+  ASSERT_EQ('\0', line[1]);
   reader.PopLine(len);
 
   ASSERT_FALSE(reader.GetNextLine(&line, &len));
@@ -133,22 +137,23 @@
 
 TEST(LineReaderTest, TwoLines) {
   const int fd = TemporaryFile();
-  write(fd, "a\nb", 3);
+  const int r = HANDLE_EINTR(write(fd, "a\nb", 3));
+  ASSERT_EQ(3, r);
   lseek(fd, 0, SEEK_SET);
   LineReader reader(fd);
 
   const char *line;
   unsigned len;
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, (unsigned)1);
-  ASSERT_EQ(line[0], 'a');
-  ASSERT_EQ(line[1], 0);
+  ASSERT_EQ((unsigned)1, len);
+  ASSERT_EQ('a', line[0]);
+  ASSERT_EQ('\0', line[1]);
   reader.PopLine(len);
 
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, (unsigned)1);
-  ASSERT_EQ(line[0], 'b');
-  ASSERT_EQ(line[1], 0);
+  ASSERT_EQ((unsigned)1, len);
+  ASSERT_EQ('b', line[0]);
+  ASSERT_EQ('\0', line[1]);
   reader.PopLine(len);
 
   ASSERT_FALSE(reader.GetNextLine(&line, &len));
@@ -160,16 +165,17 @@
   const int fd = TemporaryFile();
   char l[LineReader::kMaxLineLen - 1];
   memset(l, 'a', sizeof(l));
-  write(fd, l, sizeof(l));
+  const int r = HANDLE_EINTR(write(fd, l, sizeof(l)));
+  ASSERT_EQ(sizeof(l), r);
   lseek(fd, 0, SEEK_SET);
   LineReader reader(fd);
 
   const char *line;
   unsigned len;
   ASSERT_TRUE(reader.GetNextLine(&line, &len));
-  ASSERT_EQ(len, sizeof(l));
+  ASSERT_EQ(sizeof(l), len);
   ASSERT_TRUE(memcmp(l, line, sizeof(l)) == 0);
-  ASSERT_EQ(line[len], 0);
+  ASSERT_EQ('\0', line[len]);
 
   close(fd);
 }
@@ -178,7 +184,8 @@
   const int fd = TemporaryFile();
   char l[LineReader::kMaxLineLen];
   memset(l, 'a', sizeof(l));
-  write(fd, l, sizeof(l));
+  const int r = HANDLE_EINTR(write(fd, l, sizeof(l)));
+  ASSERT_EQ(sizeof(l), r);
   lseek(fd, 0, SEEK_SET);
   LineReader reader(fd);
 
diff --git a/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
index 1fb26ed..d04ef3e 100644
--- a/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
+++ b/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
@@ -30,11 +30,13 @@
 // linux_core_dumper_unittest.cc:
 // Unit tests for google_breakpad::LinuxCoreDumoer.
 
+#include <string>
+
 #include "breakpad_googletest_includes.h"
 #include "client/linux/minidump_writer/linux_core_dumper.h"
 #include "common/linux/tests/crash_generator.h"
+#include "common/using_std_string.h"
 
-using std::string;
 using namespace google_breakpad;
 
 TEST(LinuxCoreDumperTest, BuildProcPath) {
@@ -81,11 +83,10 @@
     return;
   }
 
-  pid_t pid = getpid();
   const string core_file = crash_generator.GetCoreFilePath();
   const string procfs_path = crash_generator.GetDirectoryOfProcFilesCopy();
   LinuxCoreDumper dumper(child_pid, core_file.c_str(), procfs_path.c_str());
-  dumper.Init();
+  EXPECT_TRUE(dumper.Init());
 
   EXPECT_TRUE(dumper.IsPostMortem());
 
diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
index 27c2e99..df4ecec 100644
--- a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
@@ -38,6 +38,7 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
+#include "processor/scoped_ptr.h"
 #include "third_party/lss/linux_syscall_support.h"
 
 #if defined(__ARM_EABI__)
@@ -51,7 +52,14 @@
 #endif
 
 void *thread_function(void *data) {
+  int pipefd = *static_cast<int *>(data);
   volatile pid_t thread_id = syscall(__NR_gettid);
+  // Signal parent that a thread has started.
+  uint8_t byte = 1;
+  if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) {
+    perror("ERROR: parent notification failed");
+    return NULL;
+  }
   register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = &thread_id;
   while (true)
     asm volatile ("" : : "r" (thread_id_ptr));
@@ -59,9 +67,9 @@
 }
 
 int main(int argc, char *argv[]) {
-  if (argc < 2) {
+  if (argc < 3) {
     fprintf(stderr,
-            "usage: linux_dumper_unittest_helper <pipe fd> <# of threads\n");
+            "usage: linux_dumper_unittest_helper <pipe fd> <# of threads>\n");
     return 1;
   }
   int pipefd = atoi(argv[1]);
@@ -70,16 +78,13 @@
     fprintf(stderr, "ERROR: number of threads is 0");
     return 1;
   }
-  pthread_t threads[num_threads];
+  google_breakpad::scoped_array<pthread_t> threads(new pthread_t[num_threads]);
   pthread_attr_t thread_attributes;
   pthread_attr_init(&thread_attributes);
   pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
   for (int i = 1; i < num_threads; i++) {
-    pthread_create(&threads[i], &thread_attributes, &thread_function, NULL);
+    pthread_create(&threads[i], &thread_attributes, &thread_function, &pipefd);
   }
-  // Signal parent that this process has started all threads.
-  uint8_t byte = 1;
-  write(pipefd, &byte, sizeof(byte));
-  thread_function(NULL);
+  thread_function(&pipefd);
   return 0;
 }
diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
index ea58dd1..864bbad 100644
--- a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
@@ -177,6 +177,7 @@
 
     line_reader->PopLine(line_len);
   }
+  sys_close(fd);
 
   if (info->ppid == -1 || info->tgid == -1)
     return false;
diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
index be014b5..b343b37 100644
--- a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+++ b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
@@ -33,11 +33,13 @@
 // This file was renamed from linux_dumper_unittest.cc and modified due
 // to LinuxDumper being splitted into two classes.
 
+#include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <unistd.h>
 #include <signal.h>
 #include <stdint.h>
+#include <string.h>
 #include <sys/mman.h>
 #include <sys/poll.h>
 #include <sys/stat.h>
@@ -47,35 +49,19 @@
 
 #include "breakpad_googletest_includes.h"
 #include "client/linux/minidump_writer/linux_ptrace_dumper.h"
+#include "client/linux/minidump_writer/minidump_writer_unittest_utils.h"
 #include "common/linux/eintr_wrapper.h"
 #include "common/linux/file_id.h"
 #include "common/linux/safe_readlink.h"
 #include "common/memory.h"
+#include "common/using_std_string.h"
 
-using std::string;
 using namespace google_breakpad;
 
 namespace {
 
 typedef testing::Test LinuxPtraceDumperTest;
 
-string GetHelperBinary() {
-  // Locate helper binary next to the current binary.
-  char self_path[PATH_MAX];
-  if (!SafeReadLink("/proc/self/exe", self_path)) {
-    return "";
-  }
-  string helper_path(self_path);
-  size_t pos = helper_path.rfind('/');
-  if (pos == string::npos) {
-    return "";
-  }
-  helper_path.erase(pos + 1);
-  helper_path += "linux_dumper_unittest_helper";
-
-  return helper_path;
-}
-
 }  // namespace
 
 TEST(LinuxPtraceDumperTest, Setup) {
@@ -134,7 +120,8 @@
   const size_t kPageSize = sysconf(_SC_PAGESIZE);
   const size_t kMappingSize = 3 * kPageSize;
   int fd = open(helper_path.c_str(), O_RDONLY);
-  ASSERT_NE(-1, fd);
+  ASSERT_NE(-1, fd) << "Failed to open file: " << helper_path
+                    << ", Error: " << strerror(errno);
   char* mapping =
     reinterpret_cast<char*>(mmap(NULL,
                                  kMappingSize,
@@ -216,20 +203,28 @@
     exit(0);
   }
   close(fds[1]);
-  // Wait for the child process to signal that it's ready.
-  struct pollfd pfd;
-  memset(&pfd, 0, sizeof(pfd));
-  pfd.fd = fds[0];
-  pfd.events = POLLIN | POLLERR;
 
-  const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
-  ASSERT_EQ(1, r);
-  ASSERT_TRUE(pfd.revents & POLLIN);
-  uint8_t junk;
-  read(fds[0], &junk, sizeof(junk));
+  // Wait for all child threads to indicate that they have started
+  for (int threads = 0; threads < kNumberOfThreadsInHelperProgram; threads++) {
+    struct pollfd pfd;
+    memset(&pfd, 0, sizeof(pfd));
+    pfd.fd = fds[0];
+    pfd.events = POLLIN | POLLERR;
+
+    const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
+    ASSERT_EQ(1, r);
+    ASSERT_TRUE(pfd.revents & POLLIN);
+    uint8_t junk;
+    ASSERT_EQ(read(fds[0], &junk, sizeof(junk)), sizeof(junk));
+  }
   close(fds[0]);
 
-  // Child is ready now.
+  // There is a race here because we may stop a child thread before
+  // it is actually running the busy loop. Empirically this sleep
+  // is sufficient to avoid the race.
+  usleep(100000);
+
+  // Children are ready now.
   LinuxPtraceDumper dumper(child_pid);
   ASSERT_TRUE(dumper.Init());
   EXPECT_EQ((size_t)kNumberOfThreadsInHelperProgram, dumper.threads().size());
@@ -256,7 +251,14 @@
                            4);
     EXPECT_EQ(dumper.threads()[i], one_thread_id);
   }
+  EXPECT_TRUE(dumper.ThreadsResume());
   kill(child_pid, SIGKILL);
+
+  // Reap child
+  int status;
+  ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0)));
+  ASSERT_TRUE(WIFSIGNALED(status));
+  ASSERT_EQ(SIGKILL, WTERMSIG(status));
 }
 #endif
 
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc
index c6feabd..209e172 100644
--- a/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/src/client/linux/minidump_writer/minidump_writer.cc
@@ -46,26 +46,27 @@
 #include "client/linux/minidump_writer/minidump_writer.h"
 #include "client/minidump_file_writer-inl.h"
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #if !defined(__ANDROID__)
 #include <link.h>
 #endif
 #include <stdio.h>
-#include <unistd.h>
-#include <ctype.h>
+#if defined(__ANDROID__)
+#include <sys/system_properties.h>
+#endif
 #if !defined(__ANDROID__)
 #include <sys/ucontext.h>
 #include <sys/user.h>
 #endif
 #include <sys/utsname.h>
+#include <unistd.h>
 
 #include <algorithm>
 
 #include "client/minidump_file_writer.h"
 #include "google_breakpad/common/minidump_format.h"
-#include "google_breakpad/common/minidump_cpu_amd64.h"
-#include "google_breakpad/common/minidump_cpu_x86.h"
 
 #if defined(__ANDROID__)
 #include "client/linux/android_link.h"
@@ -74,10 +75,11 @@
 #include "client/linux/handler/exception_handler.h"
 #include "client/linux/minidump_writer/line_reader.h"
 #include "client/linux/minidump_writer/linux_dumper.h"
-#include "client/linux/minidump_writer/linux_core_dumper.h"
 #include "client/linux/minidump_writer/linux_ptrace_dumper.h"
 #include "client/linux/minidump_writer/minidump_extension_linux.h"
+#include "client/minidump_file_writer.h"
 #include "common/linux/linux_libc_support.h"
+#include "google_breakpad/common/minidump_format.h"
 #include "third_party/lss/linux_syscall_support.h"
 
 // Minidump defines register structures which are different from the raw
@@ -1247,7 +1249,11 @@
   }
 
   bool WriteOSInformation(MDRawSystemInfo* sys_info) {
+#if defined(__ANDROID__)
+    sys_info->platform_id = MD_OS_ANDROID;
+#else
     sys_info->platform_id = MD_OS_LINUX;
+#endif
 
     struct utsname uts;
     if (uname(&uts))
@@ -1284,6 +1290,23 @@
       space_left -= info_len;
     }
 
+#ifdef __ANDROID__
+    // On Android, try to get the build fingerprint and append it.
+    // Fail gracefully because there is no guarantee that the system
+    // property will always be available or accessible.
+    char fingerprint[PROP_VALUE_MAX];
+    int fingerprint_len = __system_property_get("ro.build.fingerprint",
+                                                fingerprint);
+    // System property values shall always be zero-terminated.
+    // Be paranoid and don't trust the system.
+    if (fingerprint_len > 0 && fingerprint_len < PROP_VALUE_MAX) {
+      const char* separator = " ";
+      if (!first_item)
+        strlcat(buf, separator, buf_len);
+      strlcat(buf, fingerprint, buf_len);
+    }
+#endif
+
     MDLocationDescriptor location;
     if (!minidump_writer_.WriteString(buf, 0, &location))
       return false;
@@ -1338,12 +1361,10 @@
   return writer.Dump();
 }
 
-bool WriteMinidumpFromCore(const char* filename,
-                           const char* core_path,
-                           const char* procfs_override) {
-  MappingList mappings;
-  LinuxCoreDumper dumper(0, core_path, procfs_override);
-  MinidumpWriter writer(filename, NULL, mappings, &dumper);
+bool WriteMinidump(const char* filename,
+                   const MappingList& mappings,
+                   LinuxDumper* dumper) {
+  MinidumpWriter writer(filename, NULL, mappings, dumper);
   if (!writer.Init())
     return false;
   return writer.Dump();
diff --git a/src/client/linux/minidump_writer/minidump_writer.h b/src/client/linux/minidump_writer/minidump_writer.h
index 731249e..e79eb79 100644
--- a/src/client/linux/minidump_writer/minidump_writer.h
+++ b/src/client/linux/minidump_writer/minidump_writer.h
@@ -36,12 +36,19 @@
 #include <list>
 #include <utility>
 
+#include "client/linux/minidump_writer/linux_dumper.h"
 #include "google_breakpad/common/minidump_format.h"
 
 namespace google_breakpad {
 
+class ExceptionHandler;
+
+struct MappingEntry {
+  MappingInfo first;
+  u_int8_t second[sizeof(MDGUID)];
+};
+
 // A list of <MappingInfo, GUID>
-typedef std::pair<struct MappingInfo, u_int8_t[sizeof(MDGUID)]> MappingEntry;
 typedef std::list<MappingEntry> MappingList;
 
 // Write a minidump to the filesystem. This function does not malloc nor use
@@ -62,11 +69,9 @@
                    const void* blob, size_t blob_size,
                    const MappingList& mappings);
 
-// Write a minidump to the filesystem.  Same as above, but uses the given
-// core file and procfs directory to generate the minidump post mortem.
-bool WriteMinidumpFromCore(const char* filename,
-                           const char* core_path,
-                           const char* procfs_override);
+bool WriteMinidump(const char* filename,
+                   const MappingList& mappings,
+                   LinuxDumper* dumper);
 
 }  // namespace google_breakpad
 
diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/src/client/linux/minidump_writer/minidump_writer_unittest.cc
index ef1e7a5..4dbbbe8 100644
--- a/src/client/linux/minidump_writer/minidump_writer_unittest.cc
+++ b/src/client/linux/minidump_writer/minidump_writer_unittest.cc
@@ -40,11 +40,14 @@
 #include "client/linux/handler/exception_handler.h"
 #include "client/linux/minidump_writer/linux_dumper.h"
 #include "client/linux/minidump_writer/minidump_writer.h"
+#include "client/linux/minidump_writer/minidump_writer_unittest_utils.h"
 #include "common/linux/eintr_wrapper.h"
 #include "common/linux/file_id.h"
 #include "common/linux/safe_readlink.h"
 #include "common/tests/auto_tempdir.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/minidump.h"
+#include "processor/scoped_ptr.h"
 
 using namespace google_breakpad;
 
@@ -74,7 +77,7 @@
   memset(&context, 0, sizeof(context));
 
   AutoTempDir temp_dir;
-  std::string templ = temp_dir.path() + "/minidump-writer-unittest";
+  string templ = temp_dir.path() + "/minidump-writer-unittest";
   // Set a non-zero tid to avoid tripping asserts.
   context.tid = 1;
   ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context)));
@@ -93,7 +96,7 @@
 
   // These are defined here so the parent can use them to check the
   // data from the minidump afterwards.
-  const u_int32_t kMemorySize = sysconf(_SC_PAGESIZE);
+  const u_int32_t memory_size = sysconf(_SC_PAGESIZE);
   const char* kMemoryName = "a fake module";
   const u_int8_t kModuleGUID[sizeof(MDGUID)] = {
     0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
@@ -116,7 +119,7 @@
   // Get some memory.
   char* memory =
     reinterpret_cast<char*>(mmap(NULL,
-                                 kMemorySize,
+                                 memory_size,
                                  PROT_READ | PROT_WRITE,
                                  MAP_PRIVATE | MAP_ANON,
                                  -1,
@@ -139,12 +142,12 @@
   context.tid = 1;
 
   AutoTempDir temp_dir;
-  std::string templ = temp_dir.path() + "/minidump-writer-unittest";
+  string templ = temp_dir.path() + "/minidump-writer-unittest";
 
   // Add information about the mapped memory.
   MappingInfo info;
   info.start_addr = kMemoryAddress;
-  info.size = kMemorySize;
+  info.size = memory_size;
   info.offset = 0;
   strcpy(info.name, kMemoryName);
 
@@ -169,7 +172,7 @@
   ASSERT_TRUE(module);
 
   EXPECT_EQ(kMemoryAddress, module->base_address());
-  EXPECT_EQ(kMemorySize, module->size());
+  EXPECT_EQ(memory_size, module->size());
   EXPECT_EQ(kMemoryName, module->code_file());
   EXPECT_EQ(module_identifier, module->debug_identifier());
 
@@ -185,7 +188,7 @@
 
   // These are defined here so the parent can use them to check the
   // data from the minidump afterwards.
-  const u_int32_t kMemorySize = sysconf(_SC_PAGESIZE);
+  const u_int32_t memory_size = sysconf(_SC_PAGESIZE);
   const char* kMemoryName = "a fake module";
   const u_int8_t kModuleGUID[sizeof(MDGUID)] = {
     0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
@@ -207,19 +210,19 @@
 
   // mmap a file
   AutoTempDir temp_dir;
-  std::string tempfile = temp_dir.path() + "/minidump-writer-unittest-temp";
+  string tempfile = temp_dir.path() + "/minidump-writer-unittest-temp";
   int fd = open(tempfile.c_str(), O_RDWR | O_CREAT, 0);
   ASSERT_NE(-1, fd);
   unlink(tempfile.c_str());
   // fill with zeros
-  char buffer[kMemorySize];
-  memset(buffer, 0, kMemorySize);
-  ASSERT_EQ(kMemorySize, write(fd, buffer, kMemorySize));
+  google_breakpad::scoped_array<char> buffer(new char[memory_size]);
+  memset(buffer.get(), 0, memory_size);
+  ASSERT_EQ(memory_size, write(fd, buffer.get(), memory_size));
   lseek(fd, 0, SEEK_SET);
 
   char* memory =
     reinterpret_cast<char*>(mmap(NULL,
-                                 kMemorySize,
+                                 memory_size,
                                  PROT_READ | PROT_WRITE,
                                  MAP_PRIVATE,
                                  fd,
@@ -242,13 +245,13 @@
   memset(&context, 0, sizeof(context));
   context.tid = 1;
 
-  std::string dumpfile = temp_dir.path() + "/minidump-writer-unittest";
+  string dumpfile = temp_dir.path() + "/minidump-writer-unittest";
 
   // Add information about the mapped memory. Report it as being larger than
   // it actually is.
   MappingInfo info;
-  info.start_addr = kMemoryAddress - kMemorySize;
-  info.size = kMemorySize * 3;
+  info.start_addr = kMemoryAddress - memory_size;
+  info.size = memory_size * 3;
   info.offset = 0;
   strcpy(info.name, kMemoryName);
 
@@ -286,28 +289,19 @@
   char kNumberOfThreadsArgument[2];
   sprintf(kNumberOfThreadsArgument, "%d", kNumberOfThreadsInHelperProgram);
 
-  // Locate helper binary next to the current binary.
-  char self_path[PATH_MAX];
-  if (!SafeReadLink("/proc/self/exe", self_path)) {
-    FAIL() << "readlink failed";
+  string helper_path(GetHelperBinary());
+  if (helper_path.empty()) {
+    FAIL() << "Couldn't find helper binary";
     exit(1);
   }
-  string helper_path(self_path);
-  size_t pos = helper_path.rfind('/');
-  if (pos == string::npos) {
-    FAIL() << "no trailing slash in path: " << helper_path;
-    exit(1);
-  }
-  helper_path.erase(pos + 1);
-  helper_path += "linux_dumper_unittest_helper";
 
   // Copy binary to a temp file.
   AutoTempDir temp_dir;
-  std::string binpath = temp_dir.path() + "/linux-dumper-unittest-helper";
+  string binpath = temp_dir.path() + "/linux-dumper-unittest-helper";
   char cmdline[2 * PATH_MAX];
   sprintf(cmdline, "/bin/cp \"%s\" \"%s\"", helper_path.c_str(),
           binpath.c_str());
-  ASSERT_EQ(0, system(cmdline));
+  ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
   ASSERT_EQ(0, chmod(binpath.c_str(), 0755));
 
   int fds[2];
@@ -338,7 +332,8 @@
   ASSERT_EQ(1, r);
   ASSERT_TRUE(pfd.revents & POLLIN);
   uint8_t junk;
-  read(fds[0], &junk, sizeof(junk));
+  const int nr = HANDLE_EINTR(read(fds[0], &junk, sizeof(junk)));
+  ASSERT_EQ(sizeof(junk), nr);
   close(fds[0]);
 
   // Child is ready now.
@@ -348,7 +343,7 @@
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
 
-  std::string templ = temp_dir.path() + "/minidump-writer-unittest";
+  string templ = temp_dir.path() + "/minidump-writer-unittest";
   // Set a non-zero tid to avoid tripping asserts.
   context.tid = 1;
   ASSERT_TRUE(WriteMinidump(templ.c_str(), child_pid, &context,
@@ -379,6 +374,7 @@
                                     kGUIDStringSize);
   string module_identifier(identifier_string);
   // Strip out dashes
+  size_t pos;
   while ((pos = module_identifier.find('-')) != string::npos) {
     module_identifier.erase(pos, 1);
   }
diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc b/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
new file mode 100644
index 0000000..9f46fa6
--- /dev/null
+++ b/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 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_writer_unittest_utils.cc:
+// Shared routines used by unittests under client/linux/minidump_writer.
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include "client/linux/minidump_writer/minidump_writer_unittest_utils.h"
+#include "common/linux/safe_readlink.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+string GetHelperBinary() {
+  string helper_path;
+  char *bindir = getenv("bindir");
+  if (bindir) {
+    helper_path = string(bindir) + "/";
+  } else {
+    // Locate helper binary next to the current binary.
+    char self_path[PATH_MAX];
+    if (!SafeReadLink("/proc/self/exe", self_path)) {
+      return "";
+    }
+    helper_path = string(self_path);
+    size_t pos = helper_path.rfind('/');
+    if (pos == string::npos) {
+      return "";
+    }
+    helper_path.erase(pos + 1);
+  }
+
+  helper_path += "linux_dumper_unittest_helper";
+
+  return helper_path;
+}
+
+}  // namespace google_breakpad
diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest_utils.h b/src/client/linux/minidump_writer/minidump_writer_unittest_utils.h
new file mode 100644
index 0000000..f16cc08
--- /dev/null
+++ b/src/client/linux/minidump_writer/minidump_writer_unittest_utils.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2012, 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_writer_unittest_utils.h:
+// Shared routines used by unittests under client/linux/minidump_writer.
+
+#ifndef CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_UNITTEST_UTILS_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_UNITTEST_UTILS_H_
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+// Returns the full path to linux_dumper_unittest_helper.  The full path is
+// discovered either by using the environment variable "bindir" or by using
+// the location of the main module of the currently running process.
+string GetHelperBinary();
+
+}  // namespace google_breakpad
+
+#endif  // CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_UNITTEST_UTILS_H_
diff --git a/src/client/linux/sender/google_crash_report_sender.cc b/src/client/linux/sender/google_crash_report_sender.cc
index be897ad..0d48cbe 100644
--- a/src/client/linux/sender/google_crash_report_sender.cc
+++ b/src/client/linux/sender/google_crash_report_sender.cc
@@ -32,7 +32,7 @@
 #include <string>
 #include <iostream>
 
-using std::string;
+#include "common/using_std_string.h"
 
 DEFINE_string(crash_server, "https://clients2.google.com/cr",
               "The crash server to upload minidumps to.");
@@ -59,7 +59,7 @@
 
 
 bool CheckForRequiredFlagsOrDie() {
-  std::string error_text = "";
+  string error_text = "";
   if (FLAGS_product_name.empty()) {
     error_text.append("\nProduct name must be specified.");
   }
diff --git a/src/client/mac/Framework/OnDemandServer.h b/src/client/mac/Framework/OnDemandServer.h
index 9d8bc96..b8aabbe 100644
--- a/src/client/mac/Framework/OnDemandServer.h
+++ b/src/client/mac/Framework/OnDemandServer.h
@@ -27,13 +27,12 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#import <iostream>
-#import <mach/mach.h>
-#import <servers/bootstrap.h>
-#import <stdio.h>
-#import <stdlib.h>
-#import <sys/stat.h>
-#import <unistd.h>
+#include <mach/mach.h>
+#include <servers/bootstrap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 //==============================================================================
 // class OnDemandServer :
diff --git a/src/client/mac/handler/exception_handler.cc b/src/client/mac/handler/exception_handler.cc
index af319f6..4043019 100644
--- a/src/client/mac/handler/exception_handler.cc
+++ b/src/client/mac/handler/exception_handler.cc
@@ -485,7 +485,7 @@
         self->SuspendThreads();
 
 #if USE_PROTECTED_ALLOCATIONS
-        if(gBreakpadAllocator)
+        if (gBreakpadAllocator)
           gBreakpadAllocator->Unprotect();
 #endif
 
@@ -513,7 +513,7 @@
                                            false, false);
 
 #if USE_PROTECTED_ALLOCATIONS
-        if(gBreakpadAllocator)
+        if (gBreakpadAllocator)
           gBreakpadAllocator->Protect();
 #endif
 
@@ -534,7 +534,7 @@
           self->SuspendThreads();
 
 #if USE_PROTECTED_ALLOCATIONS
-        if(gBreakpadAllocator)
+        if (gBreakpadAllocator)
           gBreakpadAllocator->Unprotect();
 #endif
 
@@ -551,14 +551,14 @@
         // This may have become protected again within
         // WriteMinidumpWithException, but it needs to be unprotected for
         // UninstallHandler.
-        if(gBreakpadAllocator)
+        if (gBreakpadAllocator)
           gBreakpadAllocator->Unprotect();
 #endif
 
         self->UninstallHandler(true);
 
 #if USE_PROTECTED_ALLOCATIONS
-        if(gBreakpadAllocator)
+        if (gBreakpadAllocator)
           gBreakpadAllocator->Protect();
 #endif
         }
@@ -582,6 +582,10 @@
 
 //static
 void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
+#if USE_PROTECTED_ALLOCATIONS
+  if (gBreakpadAllocator)
+    gBreakpadAllocator->Unprotect();
+#endif
   gProtectedData.handler->WriteMinidumpWithException(
       EXC_SOFTWARE,
       MD_EXCEPTION_CODE_MAC_ABORT,
@@ -589,6 +593,10 @@
       mach_thread_self(),
       true,
       true);
+#if USE_PROTECTED_ALLOCATIONS
+  if (gBreakpadAllocator)
+    gBreakpadAllocator->Protect();
+#endif
 }
 
 bool ExceptionHandler::InstallHandler() {
diff --git a/src/client/mac/sender/uploader.mm b/src/client/mac/sender/uploader.mm
index b876b9e..03b4051 100644
--- a/src/client/mac/sender/uploader.mm
+++ b/src/client/mac/sender/uploader.mm
@@ -41,7 +41,7 @@
 #import "client/mac/sender/uploader.h"
 #import "common/mac/GTMLogger.h"
 
-const int kMinidumpFileLengthLimit = 800000;
+const int kMinidumpFileLengthLimit = 2 * 1024 * 1024;  // 2MB
 
 #define kApplePrefsSyncExcludeAllKey \
   @"com.apple.PreferenceSync.ExcludeAllSyncKeys"
@@ -418,6 +418,7 @@
   [googleDictionary_ setObject:@"comments" forKey:@BREAKPAD_COMMENTS];
   [googleDictionary_ setObject:@"prod" forKey:@BREAKPAD_PRODUCT];
   [googleDictionary_ setObject:@"ver" forKey:@BREAKPAD_VERSION];
+  [googleDictionary_ setObject:@"guid" forKey:@"guid"];
 
   [socorroDictionary_ setObject:@"Comments" forKey:@BREAKPAD_COMMENTS];
   [socorroDictionary_ setObject:@"CrashTime"
@@ -503,6 +504,11 @@
   if (minidumpContents_) {
     [upload addFileContents:minidumpContents_ name:@"upload_file_minidump"];
 
+    // If there is a log file, upload it together with the minidump.
+    if (logFileData_) {
+      [upload addFileContents:logFileData_ name:@"log"];
+    }
+
     // Send it
     NSError *error = nil;
     NSData *data = [upload send:&error];
@@ -543,12 +549,12 @@
                      reportID );
     }
     [result release];
+  } else {
+    // Minidump is missing -- upload just the log file.
+    if (logFileData_) {
+      [self uploadData:logFileData_ name:@"log"];
+    }
   }
-
-  if (logFileData_) {
-    [self uploadData:logFileData_ name:@"log"];
-  }
-
   [upload release];
 }
 
diff --git a/src/client/windows/common/auto_critical_section.h b/src/client/windows/common/auto_critical_section.h
index 82c7b7f..4028742 100644
--- a/src/client/windows/common/auto_critical_section.h
+++ b/src/client/windows/common/auto_critical_section.h
@@ -40,13 +40,30 @@
  public:
   // Creates a new instance with the given critical section object
   // and enters the critical section immediately.
-  explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs) {
+  explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs), taken_(false) {
     assert(cs_);
-    EnterCriticalSection(cs_);
+    Acquire();
   }
 
   // Destructor: leaves the critical section.
   ~AutoCriticalSection() {
+    if (taken_) {
+      Release();
+    }
+  }
+
+  // Enters the critical section. Recursive Acquire() calls are not allowed.
+  void Acquire() {
+    assert(!taken_);
+    EnterCriticalSection(cs_);
+    taken_ = true;
+  }
+
+  // Leaves the critical section. The caller should not call Release() unless
+  // the critical seciton has been entered already.
+  void Release() {
+    assert(taken_);
+    taken_ = false;
     LeaveCriticalSection(cs_);
   }
 
@@ -56,6 +73,7 @@
   AutoCriticalSection& operator=(const AutoCriticalSection&);
 
   CRITICAL_SECTION* cs_;
+  bool taken_;
 };
 
 }  // namespace google_breakpad
diff --git a/src/client/windows/common/ipc_protocol.h b/src/client/windows/common/ipc_protocol.h
index 7d101d3..b03c032 100644
--- a/src/client/windows/common/ipc_protocol.h
+++ b/src/client/windows/common/ipc_protocol.h
@@ -90,7 +90,8 @@
   MESSAGE_TAG_NONE = 0,
   MESSAGE_TAG_REGISTRATION_REQUEST = 1,
   MESSAGE_TAG_REGISTRATION_RESPONSE = 2,
-  MESSAGE_TAG_REGISTRATION_ACK = 3
+  MESSAGE_TAG_REGISTRATION_ACK = 3,
+  MESSAGE_TAG_UPLOAD_REQUEST = 4
 };
 
 struct CustomClientInfo {
@@ -102,7 +103,7 @@
 struct ProtocolMessage {
   ProtocolMessage()
       : tag(MESSAGE_TAG_NONE),
-        pid(0),
+        id(0),
         dump_type(MiniDumpNormal),
         thread_id(0),
         exception_pointers(NULL),
@@ -115,7 +116,7 @@
 
   // Creates an instance with the given parameters.
   ProtocolMessage(MessageTag arg_tag,
-                  DWORD arg_pid,
+                  DWORD arg_id,
                   MINIDUMP_TYPE arg_dump_type,
                   DWORD* arg_thread_id,
                   EXCEPTION_POINTERS** arg_exception_pointers,
@@ -125,7 +126,7 @@
                   HANDLE arg_dump_generated_handle,
                   HANDLE arg_server_alive)
     : tag(arg_tag),
-      pid(arg_pid),
+      id(arg_id),
       dump_type(arg_dump_type),
       thread_id(arg_thread_id),
       exception_pointers(arg_exception_pointers),
@@ -139,8 +140,9 @@
   // Tag in the message.
   MessageTag tag;
 
-  // Process id.
-  DWORD pid;
+  // The id for this message. This may be either a process id or a crash id
+  // depending on the type of message.
+  DWORD id;
 
   // Dump type requested.
   MINIDUMP_TYPE dump_type;
diff --git a/src/client/windows/crash_generation/client_info.cc b/src/client/windows/crash_generation/client_info.cc
index 94f9c3c..60bbac8 100644
--- a/src/client/windows/crash_generation/client_info.cc
+++ b/src/client/windows/crash_generation/client_info.cc
@@ -31,6 +31,7 @@
 #include "client/windows/common/ipc_protocol.h"
 
 static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime";
+static const size_t kMaxCustomInfoEntries = 4096;
 
 namespace google_breakpad {
 
@@ -52,7 +53,8 @@
       dump_requested_handle_(NULL),
       dump_generated_handle_(NULL),
       dump_request_wait_handle_(NULL),
-      process_exit_wait_handle_(NULL) {
+      process_exit_wait_handle_(NULL),
+      crash_id_(NULL) {
   GetSystemTimeAsFileTime(&start_time_);
 }
 
@@ -62,6 +64,12 @@
     return false;
   }
 
+  // The crash_id will be the low order word of the process creation time.
+  FILETIME creation_time, exit_time, kernel_time, user_time;
+  if (GetProcessTimes(process_handle_, &creation_time, &exit_time,
+                      &kernel_time, &user_time))
+    crash_id_ = creation_time.dwLowDateTime;
+
   dump_requested_handle_ = CreateEvent(NULL,    // Security attributes.
                                        TRUE,    // Manual reset.
                                        FALSE,   // Initial state.
@@ -160,6 +168,9 @@
 }
 
 bool ClientInfo::PopulateCustomInfo() {
+  if (custom_client_info_.count > kMaxCustomInfoEntries)
+    return false;
+
   SIZE_T bytes_count = 0;
   SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count;
 
diff --git a/src/client/windows/crash_generation/client_info.h b/src/client/windows/crash_generation/client_info.h
index 47a5d21..999e667 100644
--- a/src/client/windows/crash_generation/client_info.h
+++ b/src/client/windows/crash_generation/client_info.h
@@ -65,6 +65,7 @@
   HANDLE process_handle() const { return process_handle_; }
   HANDLE dump_requested_handle() const { return dump_requested_handle_; }
   HANDLE dump_generated_handle() const { return dump_generated_handle_; }
+  DWORD crash_id() const { return crash_id_; }
 
   HANDLE dump_request_wait_handle() const {
     return dump_request_wait_handle_;
@@ -160,6 +161,11 @@
   // for the client process when it signals a crash.
   FILETIME start_time_;
 
+  // The crash id which can be used to request an upload. This will be the
+  // value of the low order dword of the process creation time for the process
+  // being dumped.
+  DWORD crash_id_;
+
   // Disallow copy ctor and operator=.
   ClientInfo(const ClientInfo& client_info);
   ClientInfo& operator=(const ClientInfo& client_info);
diff --git a/src/client/windows/crash_generation/crash_generation_client.cc b/src/client/windows/crash_generation/crash_generation_client.cc
index 5e4e3cb..ffbcaf2 100644
--- a/src/client/windows/crash_generation/crash_generation_client.cc
+++ b/src/client/windows/crash_generation/crash_generation_client.cc
@@ -167,6 +167,23 @@
   return success;
 }
 
+bool CrashGenerationClient::RequestUpload(DWORD crash_id) {
+  HANDLE pipe = ConnectToServer();
+  if (!pipe) {
+    return false;
+  }
+
+  CustomClientInfo custom_info = {NULL, 0};
+  ProtocolMessage msg(MESSAGE_TAG_UPLOAD_REQUEST, crash_id,
+                      static_cast<MINIDUMP_TYPE>(NULL), NULL, NULL, NULL,
+                      custom_info, NULL, NULL, NULL);
+  DWORD bytes_count = 0;
+  bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, NULL) != 0;
+
+  CloseHandle(pipe);
+  return success;
+}
+
 HANDLE CrashGenerationClient::ConnectToServer() {
   HANDLE pipe = ConnectToPipe(pipe_name_.c_str(),
                               kPipeDesiredAccess,
@@ -223,7 +240,7 @@
   crash_event_ = reply.dump_request_handle;
   crash_generated_ = reply.dump_generated_handle;
   server_alive_ = reply.server_alive_handle;
-  server_process_id_ = reply.pid;
+  server_process_id_ = reply.id;
 
   return true;
 }
@@ -261,7 +278,7 @@
 bool CrashGenerationClient::ValidateResponse(
     const ProtocolMessage& msg) const {
   return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) &&
-         (msg.pid != 0) &&
+         (msg.id != 0) &&
          (msg.dump_request_handle != NULL) &&
          (msg.dump_generated_handle != NULL) &&
          (msg.server_alive_handle != NULL);
diff --git a/src/client/windows/crash_generation/crash_generation_client.h b/src/client/windows/crash_generation/crash_generation_client.h
index 01d13dd..85a0456 100644
--- a/src/client/windows/crash_generation/crash_generation_client.h
+++ b/src/client/windows/crash_generation/crash_generation_client.h
@@ -73,6 +73,10 @@
   // Returns true if the registration is successful; false otherwise.
   bool Register();
 
+  // Requests the crash server to upload a previous dump with the
+  // given crash id.
+  bool RequestUpload(DWORD crash_id);
+
   bool RequestDump(EXCEPTION_POINTERS* ex_info,
                    MDRawAssertionInfo* assert_info);
 
diff --git a/src/client/windows/crash_generation/crash_generation_server.cc b/src/client/windows/crash_generation/crash_generation_server.cc
index b180b2c..477973c 100644
--- a/src/client/windows/crash_generation/crash_generation_server.cc
+++ b/src/client/windows/crash_generation/crash_generation_server.cc
@@ -84,11 +84,12 @@
 static const int kShutdownSleepIntervalMs = 5;
 
 static bool IsClientRequestValid(const ProtocolMessage& msg) {
-  return msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
-         msg.pid != 0 &&
-         msg.thread_id != NULL &&
-         msg.exception_pointers != NULL &&
-         msg.assert_info != NULL;
+  return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST ||
+         (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
+          msg.id != 0 &&
+          msg.thread_id != NULL &&
+          msg.exception_pointers != NULL &&
+          msg.assert_info != NULL);
 }
 
 CrashGenerationServer::CrashGenerationServer(
@@ -100,6 +101,8 @@
     void* dump_context,
     OnClientExitedCallback exit_callback,
     void* exit_context,
+    OnClientUploadRequestCallback upload_request_callback,
+    void* upload_context,
     bool generate_dumps,
     const std::wstring* dump_path)
     : pipe_name_(pipe_name),
@@ -113,6 +116,8 @@
       dump_context_(dump_context),
       exit_callback_(exit_callback),
       exit_context_(exit_context),
+      upload_request_callback_(upload_request_callback),
+      upload_context_(upload_context),
       generate_dumps_(generate_dumps),
       dump_generator_(NULL),
       server_state_(IPC_SERVER_STATE_UNINITIALIZED),
@@ -120,7 +125,7 @@
       overlapped_(),
       client_info_(NULL),
       cleanup_item_count_(0) {
-  InitializeCriticalSection(&clients_sync_);
+  InitializeCriticalSection(&sync_);
 
   if (dump_path) {
     dump_generator_.reset(new MinidumpGenerator(*dump_path));
@@ -128,38 +133,41 @@
 }
 
 CrashGenerationServer::~CrashGenerationServer() {
-  // Indicate to existing threads that server is shutting down.
-  shutting_down_ = true;
-
-  // Even if there are no current worker threads running, it is possible that
-  // an I/O request is pending on the pipe right now but not yet done. In fact,
-  // it's very likely this is the case unless we are in an ERROR state. If we
-  // don't wait for the pending I/O to be done, then when the I/O completes,
-  // it may write to invalid memory. AppVerifier will flag this problem too.
-  // So we disconnect from the pipe and then wait for the server to get into
-  // error state so that the pending I/O will fail and get cleared.
-  DisconnectNamedPipe(pipe_);
-  int num_tries = 100;
-  while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) {
-    Sleep(10);
-  }
-
-  // Unregister wait on the pipe.
-  if (pipe_wait_handle_) {
-    // Wait for already executing callbacks to finish.
-    UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE);
-  }
-
-  // Close the pipe to avoid further client connections.
-  if (pipe_) {
-    CloseHandle(pipe_);
-  }
-
-  // Request all ClientInfo objects to unregister all waits.
-  // New scope to hold the lock for the shortest time.
+  // New scope to release the lock automatically.
   {
-    AutoCriticalSection lock(&clients_sync_);
+    AutoCriticalSection lock(&sync_);
 
+    // Indicate to existing threads that server is shutting down.
+    shutting_down_ = true;
+
+    // Even if there are no current worker threads running, it is possible that
+    // an I/O request is pending on the pipe right now but not yet done.
+    // In fact, it's very likely this is the case unless we are in an ERROR
+    // state. If we don't wait for the pending I/O to be done, then when the I/O
+    // completes, it may write to invalid memory. AppVerifier will flag this
+    // problem too. So we disconnect from the pipe and then wait for the server
+    // to get into error state so that the pending I/O will fail and get
+    // cleared.
+    DisconnectNamedPipe(pipe_);
+    int num_tries = 100;
+    while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) {
+      lock.Release();
+      Sleep(10);
+      lock.Acquire();
+    }
+
+    // Unregister wait on the pipe.
+    if (pipe_wait_handle_) {
+      // Wait for already executing callbacks to finish.
+      UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE);
+    }
+
+    // Close the pipe to avoid further client connections.
+    if (pipe_) {
+      CloseHandle(pipe_);
+    }
+
+    // Request all ClientInfo objects to unregister all waits.
     std::list<ClientInfo*>::iterator iter;
     for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
       ClientInfo* client_info = *iter;
@@ -180,33 +188,35 @@
     }
   }
 
-  // Clean up all the ClientInfo objects.
   // New scope to hold the lock for the shortest time.
   {
-    AutoCriticalSection lock(&clients_sync_);
+    AutoCriticalSection lock(&sync_);
 
+    // Clean up all the ClientInfo objects.
     std::list<ClientInfo*>::iterator iter;
     for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
       ClientInfo* client_info = *iter;
       delete client_info;
     }
+
+    if (server_alive_handle_) {
+      // Release the mutex before closing the handle so that clients requesting
+      // dumps wait for a long time for the server to generate a dump.
+      ReleaseMutex(server_alive_handle_);
+      CloseHandle(server_alive_handle_);
+    }
+
+    if (overlapped_.hEvent) {
+      CloseHandle(overlapped_.hEvent);
+    }
   }
 
-  if (server_alive_handle_) {
-    // Release the mutex before closing the handle so that clients requesting
-    // dumps wait for a long time for the server to generate a dump.
-    ReleaseMutex(server_alive_handle_);
-    CloseHandle(server_alive_handle_);
-  }
-
-  if (overlapped_.hEvent) {
-    CloseHandle(overlapped_.hEvent);
-  }
-
-  DeleteCriticalSection(&clients_sync_);
+  DeleteCriticalSection(&sync_);
 }
 
 bool CrashGenerationServer::Start() {
+  AutoCriticalSection lock(&sync_);
+
   if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) {
     return false;
   }
@@ -416,9 +426,16 @@
     return;
   }
 
+  if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) {
+    if (upload_request_callback_)
+      upload_request_callback_(upload_context_, msg_.id);
+    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+    return;
+  }
+
   scoped_ptr<ClientInfo> client_info(
       new ClientInfo(this,
-                     msg_.pid,
+                     msg_.id,
                      msg_.dump_type,
                      msg_.thread_id,
                      msg_.exception_pointers,
@@ -582,7 +599,7 @@
 bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info,
                                          ProtocolMessage* reply) const {
   reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE;
-  reply->pid = GetCurrentProcessId();
+  reply->id = GetCurrentProcessId();
 
   if (CreateClientHandles(client_info, reply)) {
     return true;
@@ -670,6 +687,8 @@
 // implements the state machine described in ReadMe.txt along with the
 // helper methods HandleXXXState.
 void CrashGenerationServer::HandleConnectionRequest() {
+  AutoCriticalSection lock(&sync_);
+
   // If we are shutting doen then get into ERROR state, reset the event so more
   // workers don't run and return immediately.
   if (shutting_down_) {
@@ -756,7 +775,7 @@
 
   // New scope to hold the lock for the shortest time.
   {
-    AutoCriticalSection lock(&clients_sync_);
+    AutoCriticalSection lock(&sync_);
     clients_.push_back(client_info);
   }
 
@@ -824,7 +843,7 @@
 
   // Start a new scope to release lock automatically.
   {
-    AutoCriticalSection lock(&clients_sync_);
+    AutoCriticalSection lock(&sync_);
     clients_.remove(client_info);
   }
 
diff --git a/src/client/windows/crash_generation/crash_generation_server.h b/src/client/windows/crash_generation/crash_generation_server.h
index 31a353b..ea3776f 100644
--- a/src/client/windows/crash_generation/crash_generation_server.h
+++ b/src/client/windows/crash_generation/crash_generation_server.h
@@ -59,6 +59,9 @@
   typedef void (*OnClientExitedCallback)(void* context,
                                          const ClientInfo* client_info);
 
+  typedef void (*OnClientUploadRequestCallback)(void* context,
+                                                const DWORD crash_id);
+
   // Creates an instance with the given parameters.
   //
   // Parameter pipe_name: Name of the Windows named pipe
@@ -86,6 +89,8 @@
                         void* dump_context,
                         OnClientExitedCallback exit_callback,
                         void* exit_context,
+                        OnClientUploadRequestCallback upload_request_callback,
+                        void* upload_context,
                         bool generate_dumps,
                         const std::wstring* dump_path);
 
@@ -211,8 +216,9 @@
   // asynchronous IO operation.
   void EnterStateWhenSignaled(IPCServerState state);
 
-  // Sync object for thread-safe access to the shared list of clients.
-  CRITICAL_SECTION clients_sync_;
+  // Sync object for thread-safe access to the shared list of clients and
+  // the server's state.
+  CRITICAL_SECTION sync_;
 
   // List of clients.
   std::list<ClientInfo*> clients_;
@@ -250,6 +256,12 @@
   // Context for client process exit callback.
   void* exit_context_;
 
+  // Callback for upload request.
+  OnClientUploadRequestCallback upload_request_callback_;
+
+  // Context for upload request callback.
+  void* upload_context_;
+
   // Whether to generate dumps.
   bool generate_dumps_;
 
@@ -260,10 +272,10 @@
   // Note that since we restrict the pipe to one instance, we
   // only need to keep one state of the server. Otherwise, server
   // would have one state per client it is talking to.
-  volatile IPCServerState server_state_;
+  IPCServerState server_state_;
 
   // Whether the server is shutting down.
-  volatile bool shutting_down_;
+  bool shutting_down_;
 
   // Overlapped instance for async I/O on the pipe.
   OVERLAPPED overlapped_;
diff --git a/src/client/windows/crash_generation/minidump_generator.cc b/src/client/windows/crash_generation/minidump_generator.cc
index 37bd55e..fe4937a 100644
--- a/src/client/windows/crash_generation/minidump_generator.cc
+++ b/src/client/windows/crash_generation/minidump_generator.cc
@@ -28,12 +28,218 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "client/windows/crash_generation/minidump_generator.h"
-#include <cassert>
+
+#include <assert.h>
+#include <avrfsdk.h>
+
+#include <algorithm>
+#include <list>
+#include <vector>
+
 #include "client/windows/common/auto_critical_section.h"
 #include "common/windows/guid_string.h"
 
 using std::wstring;
 
+// Disable C4996: 'std::copy': Function call with parameters that may be unsafe.
+#pragma warning( disable : 4996 )
+
+namespace {
+
+// A helper class used to collect handle operations data. Unlike
+// |MiniDumpWithHandleData| it records the operations for a single handle value
+// only, making it possible to include this information to a minidump.
+class HandleTraceData {
+ public:
+  HandleTraceData();
+  ~HandleTraceData();
+
+  // Collects the handle operations data and formats a user stream to be added
+  // to the minidump.
+  bool CollectHandleData(HANDLE process_handle,
+                         EXCEPTION_POINTERS* exception_pointers);
+
+  // Fills the user dump entry with a pointer to the collected handle operations
+  // data. Returns |true| if the entry was initialized successfully, or |false|
+  // if no trace data is available.
+  bool GetUserStream(MINIDUMP_USER_STREAM* user_stream);
+
+ private:
+  // Reads the exception code from the client process's address space.
+  // This routine assumes that the client process's pointer width matches ours.
+  static bool ReadExceptionCode(HANDLE process_handle,
+                                EXCEPTION_POINTERS* exception_pointers,
+                                DWORD* exception_code);
+
+  // Stores handle operations retrieved by VerifierEnumerateResource().
+  static ULONG CALLBACK RecordHandleOperations(void* resource_description,
+                                               void* enumeration_context,
+                                               ULONG* enumeration_level);
+
+  // Function pointer type for VerifierEnumerateResource, which is looked up
+  // dynamically.
+  typedef BOOL (WINAPI* VerifierEnumerateResourceType)(
+      HANDLE Process,
+      ULONG Flags,
+      ULONG ResourceType,
+      AVRF_RESOURCE_ENUMERATE_CALLBACK ResourceCallback,
+      PVOID EnumerationContext);
+
+  // Handle to dynamically loaded verifier.dll.
+  HMODULE verifier_module_;
+
+  // Pointer to the VerifierEnumerateResource function.
+  VerifierEnumerateResourceType enumerate_resource_;
+
+  // Handle value to look for.
+  ULONG64 handle_;
+
+  // List of handle operations for |handle_|.
+  std::list<AVRF_HANDLE_OPERATION> operations_;
+
+  // Minidump stream data.
+  std::vector<char> stream_;
+};
+
+HandleTraceData::HandleTraceData()
+    : verifier_module_(NULL),
+      enumerate_resource_(NULL),
+      handle_(NULL) {
+}
+
+HandleTraceData::~HandleTraceData() {
+  if (verifier_module_) {
+    FreeLibrary(verifier_module_);
+  }
+}
+
+bool HandleTraceData::CollectHandleData(
+    HANDLE process_handle,
+    EXCEPTION_POINTERS* exception_pointers) {
+  DWORD exception_code;
+  if (!ReadExceptionCode(process_handle, exception_pointers, &exception_code)) {
+    return false;
+  }
+
+  // Verify whether the execption is STATUS_INVALID_HANDLE. Do not record any
+  // handle information if it is a different exception to keep the minidump
+  // small.
+  if (exception_code != STATUS_INVALID_HANDLE) {
+    return true;
+  }
+
+  // Load verifier!VerifierEnumerateResource() dynamically.
+  verifier_module_ = LoadLibrary(TEXT("verifier.dll"));
+  if (!verifier_module_) {
+    return false;
+  }
+
+  enumerate_resource_ = reinterpret_cast<VerifierEnumerateResourceType>(
+      GetProcAddress(verifier_module_, "VerifierEnumerateResource"));
+  if (!enumerate_resource_) {
+    return false;
+  }
+
+  // STATUS_INVALID_HANDLE does not provide the offending handle value in
+  // the exception parameters so we have to guess. At the moment we scan
+  // the handle operations trace looking for the last invalid handle operation
+  // and record only the operations for that handle value.
+  if (enumerate_resource_(process_handle,
+                          0,
+                          AvrfResourceHandleTrace,
+                          &RecordHandleOperations,
+                          this) != ERROR_SUCCESS) {
+    // The handle tracing must have not been enabled.
+    return true;
+  }
+
+  // Now that |handle_| is initialized, purge all irrelevant operations.
+  std::list<AVRF_HANDLE_OPERATION>::iterator i = operations_.begin();
+  std::list<AVRF_HANDLE_OPERATION>::iterator i_end = operations_.end();
+  while (i != i_end) {
+    if (i->Handle == handle_) {
+      ++i;
+    } else {
+      i = operations_.erase(i);
+    }
+  }
+
+  // Convert the list of recorded operations to a minidump stream.
+  stream_.resize(sizeof(MINIDUMP_HANDLE_OPERATION_LIST) +
+      sizeof(AVRF_HANDLE_OPERATION) * operations_.size());
+
+  MINIDUMP_HANDLE_OPERATION_LIST* stream_data =
+      reinterpret_cast<MINIDUMP_HANDLE_OPERATION_LIST*>(
+          &stream_.front());
+  stream_data->SizeOfHeader = sizeof(MINIDUMP_HANDLE_OPERATION_LIST);
+  stream_data->SizeOfEntry = sizeof(AVRF_HANDLE_OPERATION);
+  stream_data->NumberOfEntries = static_cast<ULONG32>(operations_.size());
+  stream_data->Reserved = 0;
+  std::copy(operations_.begin(),
+            operations_.end(),
+            reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1));
+
+  return true;
+}
+
+bool HandleTraceData::GetUserStream(MINIDUMP_USER_STREAM* user_stream) {
+  if (stream_.empty()) {
+    return false;
+  } else {
+    user_stream->Type = HandleOperationListStream;
+    user_stream->BufferSize = static_cast<ULONG>(stream_.size());
+    user_stream->Buffer = &stream_.front();
+    return true;
+  }
+}
+
+bool HandleTraceData::ReadExceptionCode(
+    HANDLE process_handle,
+    EXCEPTION_POINTERS* exception_pointers,
+    DWORD* exception_code) {
+  EXCEPTION_POINTERS pointers;
+  if (!ReadProcessMemory(process_handle,
+                         exception_pointers,
+                         &pointers,
+                         sizeof(pointers),
+                         NULL)) {
+    return false;
+  }
+
+  if (!ReadProcessMemory(process_handle,
+                         pointers.ExceptionRecord,
+                         exception_code,
+                         sizeof(*exception_code),
+                         NULL)) {
+    return false;
+  }
+
+  return true;
+}
+
+ULONG CALLBACK HandleTraceData::RecordHandleOperations(
+    void* resource_description,
+    void* enumeration_context,
+    ULONG* enumeration_level) {
+  AVRF_HANDLE_OPERATION* description =
+      reinterpret_cast<AVRF_HANDLE_OPERATION*>(resource_description);
+  HandleTraceData* self =
+      reinterpret_cast<HandleTraceData*>(enumeration_context);
+
+  // Remember the last invalid handle operation.
+  if (description->OperationType == OperationDbBADREF) {
+    self->handle_ = description->Handle;
+  }
+
+  // Record all handle operations.
+  self->operations_.push_back(*description);
+
+  *enumeration_level = HeapEnumerationEverything;
+  return ERROR_SUCCESS;
+}
+
+}  // namespace
+
 namespace google_breakpad {
 
 MinidumpGenerator::MinidumpGenerator(const wstring& dump_path)
@@ -162,8 +368,9 @@
     breakpad_info.requesting_thread_id = requesting_thread_id;
   }
 
-  // Leave room in user_stream_array for a possible assertion info stream.
-  MINIDUMP_USER_STREAM user_stream_array[2];
+  // Leave room in user_stream_array for possible assertion info and handle
+  // operations streams.
+  MINIDUMP_USER_STREAM user_stream_array[3];
   user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM;
   user_stream_array[0].BufferSize = sizeof(breakpad_info);
   user_stream_array[0].Buffer = &breakpad_info;
@@ -207,6 +414,39 @@
     ++user_streams.UserStreamCount;
   }
 
+  // If the process is terminated by STATUS_INVALID_HANDLE exception store
+  // the trace of operatios for the offending handle value. Do nothing special
+  // if the client already requested the handle trace to be stored in the dump.
+  HandleTraceData handle_trace_data;
+  if (exception_pointers && (dump_type & MiniDumpWithHandleData) == 0) {
+    if (!handle_trace_data.CollectHandleData(process_handle,
+                                             exception_pointers)) {
+      CloseHandle(dump_file);
+      if (full_dump_file != INVALID_HANDLE_VALUE)
+        CloseHandle(full_dump_file);
+      return false;
+    }
+  }
+
+  bool result_full_memory = true;
+  if (full_memory_dump) {
+    result_full_memory = write_dump(
+        process_handle,
+        process_id,
+        full_dump_file,
+        static_cast<MINIDUMP_TYPE>((dump_type & (~MiniDumpNormal))
+                                    | MiniDumpWithHandleData),
+        exception_pointers ? &dump_exception_info : NULL,
+        &user_streams,
+        NULL) != FALSE;
+  }
+
+  // Add handle operations trace stream to the minidump if it was collected.
+  if (handle_trace_data.GetUserStream(
+          &user_stream_array[user_streams.UserStreamCount])) {
+    ++user_streams.UserStreamCount;
+  }
+
   bool result_minidump = write_dump(
       process_handle,
       process_id,
@@ -217,18 +457,6 @@
       &user_streams,
       NULL) != FALSE;
 
-  bool result_full_memory = true;
-  if (full_memory_dump) {
-    result_full_memory = write_dump(
-        process_handle,
-        process_id,
-        full_dump_file,
-        static_cast<MINIDUMP_TYPE>(dump_type & (~MiniDumpNormal)),
-        exception_pointers ? &dump_exception_info : NULL,
-        &user_streams,
-        NULL) != FALSE;
-  }
-
   bool result = result_minidump && result_full_memory;
 
   CloseHandle(dump_file);
diff --git a/src/client/windows/handler/exception_handler.cc b/src/client/windows/handler/exception_handler.cc
index 7ce2ca9..08c5fb5 100644
--- a/src/client/windows/handler/exception_handler.cc
+++ b/src/client/windows/handler/exception_handler.cc
@@ -312,6 +312,10 @@
   }
 }
 
+bool ExceptionHandler::RequestUpload(DWORD crash_id) {
+  return crash_generation_client_->RequestUpload(crash_id);
+}
+
 // static
 DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) {
   ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter);
diff --git a/src/client/windows/handler/exception_handler.h b/src/client/windows/handler/exception_handler.h
index 2c2e7b7..6c5ee76 100644
--- a/src/client/windows/handler/exception_handler.h
+++ b/src/client/windows/handler/exception_handler.h
@@ -88,9 +88,9 @@
   // 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.
+  // 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);
 
@@ -177,6 +177,9 @@
     UpdateNextID();  // Necessary to put dump_path_ in next_minidump_path_.
   }
 
+  // Requests that a previously reported crash be uploaded.
+  bool RequestUpload(DWORD crash_id);
+
   // Writes a minidump immediately.  This can be used to capture the
   // execution state independently of a crash.  Returns true on success.
   bool WriteMinidump();
diff --git a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc
index 1b4bd3c..e36c1d1 100644
--- a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc
+++ b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc
@@ -291,6 +291,8 @@
                                            NULL,
                                            ShowClientExited,
                                            NULL,
+                                           NULL,
+                                           NULL,
                                            true,
                                            &dump_path);
 
diff --git a/src/client/windows/unittests/crash_generation_server_test.cc b/src/client/windows/unittests/crash_generation_server_test.cc
index ce49439..cf95d43 100644
--- a/src/client/windows/unittests/crash_generation_server_test.cc
+++ b/src/client/windows/unittests/crash_generation_server_test.cc
@@ -65,6 +65,7 @@
                                  CallOnClientConnected, &mock_callbacks_,
                                  CallOnClientDumpRequested, &mock_callbacks_,
                                  CallOnClientExited, &mock_callbacks_,
+                                 CallOnClientUploadRequested, &mock_callbacks_,
                                  false,
                                  NULL),
         thread_id_(0),
@@ -82,6 +83,8 @@
                       const std::wstring* file_path));
     MOCK_METHOD1(OnClientExited,
                  void(const google_breakpad::ClientInfo* client_info));
+    MOCK_METHOD1(OnClientUploadRequested,
+                 void(const DWORD crash_id));
   };
 
   enum ClientFault {
@@ -248,6 +251,11 @@
       OnClientExited(client_info);
   }
 
+  static void CallOnClientUploadRequested(void* context, const DWORD crash_id) {
+    static_cast<MockCrashGenerationServerCallbacks*>(context)->
+      OnClientUploadRequested(crash_id);
+  }
+
   DWORD thread_id_;
   EXCEPTION_POINTERS* exception_pointers_;
   MDRawAssertionInfo assert_info_;
diff --git a/src/client/windows/unittests/exception_handler_death_test.cc b/src/client/windows/unittests/exception_handler_death_test.cc
index adea044..514ee72 100644
--- a/src/client/windows/unittests/exception_handler_death_test.cc
+++ b/src/client/windows/unittests/exception_handler_death_test.cc
@@ -161,8 +161,8 @@
   ASSERT_TRUE(DoesPathExist(temp_path_));
   std::wstring dump_path(temp_path_);
   google_breakpad::CrashGenerationServer server(
-    kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, true,
-    &dump_path);
+    kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL,
+    NULL, true, &dump_path);
 
   // This HAS to be EXPECT_, because when this test case is executed in the
   // child process, the server registration will fail due to the named pipe
diff --git a/src/client/windows/unittests/exception_handler_test.cc b/src/client/windows/unittests/exception_handler_test.cc
index f034188..74d9a9b 100644
--- a/src/client/windows/unittests/exception_handler_test.cc
+++ b/src/client/windows/unittests/exception_handler_test.cc
@@ -220,8 +220,8 @@
   ASSERT_TRUE(DoesPathExist(temp_path_));
   wstring dump_path(temp_path_);
   google_breakpad::CrashGenerationServer server(
-      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, true,
-      &dump_path);
+      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
+      NULL, true, &dump_path);
 
   ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
 
@@ -291,8 +291,8 @@
   ASSERT_TRUE(DoesPathExist(temp_path_));
   wstring dump_path(temp_path_);
   google_breakpad::CrashGenerationServer server(
-      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, true,
-      &dump_path);
+      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
+      NULL, true, &dump_path);
 
   ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
 
diff --git a/src/common/basictypes.h b/src/common/basictypes.h
index 694f702..84668b7 100644
--- a/src/common/basictypes.h
+++ b/src/common/basictypes.h
@@ -32,8 +32,10 @@
 
 // A macro to disallow the copy constructor and operator= functions
 // This should be used in the private: declarations for a class
+#ifndef DISALLOW_COPY_AND_ASSIGN
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
   TypeName(const TypeName&);               \
   void operator=(const TypeName&)
+#endif  // DISALLOW_COPY_AND_ASSIGN
 
 #endif  // COMMON_BASICTYPES_H_
diff --git a/src/common/byte_cursor.h b/src/common/byte_cursor.h
index 24ffce7..accd54e 100644
--- a/src/common/byte_cursor.h
+++ b/src/common/byte_cursor.h
@@ -45,6 +45,8 @@
 #include <string.h>
 #include <string>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
 // A buffer holding a series of bytes.
@@ -164,7 +166,7 @@
   // byte buffer does not contain a terminating zero, clear this cursor's
   // complete_ flag, and set STR to the empty string. Return a reference to
   // this cursor.
-  ByteCursor &CString(std::string *str) {
+  ByteCursor &CString(string *str) {
     const uint8_t *end
       = static_cast<const uint8_t *>(memchr(here_, '\0', Available()));
     if (end) {
@@ -191,7 +193,7 @@
   //   
   // - Otherwise, set *STR to a copy of those LIMIT bytes, and advance the
   //   cursor by LIMIT bytes.
-  ByteCursor &CString(std::string *str, size_t limit) {
+  ByteCursor &CString(string *str, size_t limit) {
     if (CheckAvailable(limit)) {
       const uint8_t *end
         = static_cast<const uint8_t *>(memchr(here_, '\0', limit));
diff --git a/src/common/byte_cursor_unittest.cc b/src/common/byte_cursor_unittest.cc
index 0ab4770..06bfd89 100644
--- a/src/common/byte_cursor_unittest.cc
+++ b/src/common/byte_cursor_unittest.cc
@@ -36,12 +36,12 @@
 
 #include <string.h>
 
-#include "common/byte_cursor.h"
 #include "breakpad_googletest_includes.h"
+#include "common/byte_cursor.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::ByteBuffer;
 using google_breakpad::ByteCursor;
-using std::string;
 
 TEST(Buffer, SizeOfNothing) {
   uint8_t data[1];
diff --git a/src/common/dwarf/bytereader_unittest.cc b/src/common/dwarf/bytereader_unittest.cc
index d839dbe..4311ab6 100644
--- a/src/common/dwarf/bytereader_unittest.cc
+++ b/src/common/dwarf/bytereader_unittest.cc
@@ -37,6 +37,7 @@
 #include "common/dwarf/bytereader.h"
 #include "common/dwarf/bytereader-inl.h"
 #include "common/dwarf/cfi_assembler.h"
+#include "common/using_std_string.h"
 
 using dwarf2reader::ByteReader;
 using dwarf2reader::DwarfPointerEncoding;
@@ -47,7 +48,6 @@
 using google_breakpad::test_assembler::kBigEndian;
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Section;
-using std::string;
 using testing::Test;
 
 struct ReaderFixture {
diff --git a/src/common/dwarf/cfi_assembler.h b/src/common/dwarf/cfi_assembler.h
index 3f30503..00ff6f0 100644
--- a/src/common/dwarf/cfi_assembler.h
+++ b/src/common/dwarf/cfi_assembler.h
@@ -41,6 +41,7 @@
 
 #include "common/dwarf/dwarf2enums.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
@@ -49,7 +50,6 @@
 using google_breakpad::test_assembler::Endianness;
 using google_breakpad::test_assembler::Label;
 using google_breakpad::test_assembler::Section;
-using std::string;
 
 class CFISection: public Section {
  public:
diff --git a/src/common/dwarf/dwarf2diehandler.cc b/src/common/dwarf/dwarf2diehandler.cc
index 1639954..c741d69 100644
--- a/src/common/dwarf/dwarf2diehandler.cc
+++ b/src/common/dwarf/dwarf2diehandler.cc
@@ -31,10 +31,13 @@
 // dwarf2diehandler.cc: Implement the dwarf2reader::DieDispatcher class.
 // See dwarf2diehandler.h for details.
 
-#include "common/dwarf/dwarf2diehandler.h"
-
 #include <assert.h>
 
+#include <string>
+
+#include "common/dwarf/dwarf2diehandler.h"
+#include "common/using_std_string.h"
+
 namespace dwarf2reader {
 
 DIEDispatcher::~DIEDispatcher() {
@@ -176,7 +179,7 @@
 void DIEDispatcher::ProcessAttributeString(uint64 offset,
                                            enum DwarfAttribute attr,
                                            enum DwarfForm form,
-                                           const std::string& data) {
+                                           const string& data) {
   HandlerStack &current = die_handlers_.top();
   // This had better be an attribute of the DIE we were meant to handle.
   assert(offset == current.offset_);
diff --git a/src/common/dwarf/dwarf2diehandler.h b/src/common/dwarf/dwarf2diehandler.h
index 5d899bf..12b8d3a 100644
--- a/src/common/dwarf/dwarf2diehandler.h
+++ b/src/common/dwarf/dwarf2diehandler.h
@@ -157,10 +157,12 @@
 #define COMMON_DWARF_DWARF2DIEHANDLER_H__
 
 #include <stack>
+#include <string>
 
 #include "common/dwarf/types.h"
 #include "common/dwarf/dwarf2enums.h"
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 
 namespace dwarf2reader {
 
@@ -208,7 +210,7 @@
                                       uint64 len) { }
   virtual void ProcessAttributeString(enum DwarfAttribute attr,
                                       enum DwarfForm form,
-                                      const std::string& data) { }
+                                      const string& data) { }
   virtual void ProcessAttributeSignature(enum DwarfAttribute attr,
                                          enum DwarfForm form,
                                          uint64 signture) { }
@@ -316,7 +318,7 @@
   void ProcessAttributeString(uint64 offset,
                               enum DwarfAttribute attr,
                               enum DwarfForm form,
-                              const std::string &data);
+                              const string &data);
   void ProcessAttributeSignature(uint64 offset,
                                  enum DwarfAttribute attr,
                                  enum DwarfForm form,
diff --git a/src/common/dwarf/dwarf2diehandler_unittest.cc b/src/common/dwarf/dwarf2diehandler_unittest.cc
index 186b951..6a73119 100644
--- a/src/common/dwarf/dwarf2diehandler_unittest.cc
+++ b/src/common/dwarf/dwarf2diehandler_unittest.cc
@@ -38,9 +38,9 @@
 #include "breakpad_googletest_includes.h"
 
 #include "common/dwarf/dwarf2diehandler.h"
+#include "common/using_std_string.h"
 
 using std::make_pair;
-using std::string;
 
 using ::testing::_;
 using ::testing::ContainerEq;
diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc
index b4e6113..7c1a29d 100644
--- a/src/common/dwarf/dwarf2reader.cc
+++ b/src/common/dwarf/dwarf2reader.cc
@@ -41,11 +41,13 @@
 #include <map>
 #include <memory>
 #include <stack>
+#include <string>
 #include <utility>
 
 #include "common/dwarf/bytereader-inl.h"
 #include "common/dwarf/bytereader.h"
 #include "common/dwarf/line_state_machine.h"
+#include "common/using_std_string.h"
 
 namespace dwarf2reader {
 
@@ -1004,7 +1006,7 @@
 // Rule: EXPRESSION evaluates to the address at which the register is saved.
 class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule {
  public:
-  explicit ExpressionRule(const std::string &expression)
+  explicit ExpressionRule(const string &expression)
       : expression_(expression) { }
   ~ExpressionRule() { }
   bool Handle(Handler *handler, uint64 address, int reg) const {
@@ -1018,13 +1020,13 @@
   }
   Rule *Copy() const { return new ExpressionRule(*this); }
  private:
-  std::string expression_;
+  string expression_;
 };
 
 // Rule: EXPRESSION evaluates to the address at which the register is saved.
 class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule {
  public:
-  explicit ValExpressionRule(const std::string &expression)
+  explicit ValExpressionRule(const string &expression)
       : expression_(expression) { }
   ~ValExpressionRule() { }
   bool Handle(Handler *handler, uint64 address, int reg) const {
@@ -1039,7 +1041,7 @@
   }
   Rule *Copy() const { return new ValExpressionRule(*this); }
  private:
-  std::string expression_;
+  string expression_;
 };
 
 // A map from register numbers to rules.
@@ -1220,7 +1222,7 @@
     unsigned register_number;  // A register number.
     uint64 offset;             // An offset or address.
     long signed_offset;        // A signed offset.
-    std::string expression;    // A DWARF expression.
+    string expression;         // A DWARF expression.
   };
 
   // Parse CFI instruction operands from STATE's instruction stream as
@@ -1407,7 +1409,7 @@
         if (len > bytes_left || expression_length > bytes_left - len)
           return ReportIncomplete();
         cursor_ += len;
-        operands->expression = std::string(cursor_, expression_length);
+        operands->expression = string(cursor_, expression_length);
         cursor_ += expression_length;
         break;
       }
@@ -1857,20 +1859,14 @@
   cie->version = reader_->ReadOneByte(cursor);
   cursor++;
 
-  // If we don't recognize the version, we can't parse any more fields
-  // of the CIE. For DWARF CFI, we handle versions 1 through 3 (there
-  // was never a version 2 of CFI data). For .eh_frame, we handle only
-  // version 1.
-  if (eh_frame_) {
-    if (cie->version != 1) {
-      reporter_->UnrecognizedVersion(cie->offset, cie->version);
-      return false;
-    }
-  } else {
-    if (cie->version < 1 || cie->version > 3) {
-      reporter_->UnrecognizedVersion(cie->offset, cie->version);
-      return false;
-    }
+  // If we don't recognize the version, we can't parse any more fields of the
+  // CIE. For DWARF CFI, we handle versions 1 through 3 (there was never a
+  // version 2 of CFI data). For .eh_frame, we handle versions 1 and 3 as well;
+  // the difference between those versions seems to be the same as for
+  // .debug_frame.
+  if (cie->version < 1 || cie->version > 3) {
+    reporter_->UnrecognizedVersion(cie->offset, cie->version);
+    return false;
   }
 
   const char *augmentation_start = cursor;
@@ -1878,7 +1874,7 @@
       memchr(augmentation_start, '\0', cie->end - augmentation_start);
   if (! augmentation_end) return ReportIncomplete(cie);
   cursor = static_cast<const char *>(augmentation_end);
-  cie->augmentation = std::string(augmentation_start,
+  cie->augmentation = string(augmentation_start,
                                   cursor - augmentation_start);
   // Skip the terminating '\0'.
   cursor++;
@@ -2266,7 +2262,7 @@
 }
 
 void CallFrameInfo::Reporter::UnrecognizedAugmentation(uint64 offset,
-                                                       const std::string &aug) {
+                                                       const string &aug) {
   fprintf(stderr,
           "%s: CFI frame description entry at offset 0x%llx in '%s':"
           " CIE specifies unrecognized augmentation: '%s'\n",
diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h
index cd61fb5..ecf4eb2 100644
--- a/src/common/dwarf/dwarf2reader.h
+++ b/src/common/dwarf/dwarf2reader.h
@@ -49,6 +49,7 @@
 #include "common/dwarf/bytereader.h"
 #include "common/dwarf/dwarf2enums.h"
 #include "common/dwarf/types.h"
+#include "common/using_std_string.h"
 
 namespace dwarf2reader {
 struct LineStateMachine;
@@ -57,7 +58,7 @@
 
 // This maps from a string naming a section to a pair containing a
 // the data for the section, and the size of the section.
-typedef std::map<std::string, std::pair<const char*, uint64> > SectionMap;
+typedef std::map<string, std::pair<const char*, uint64> > SectionMap;
 typedef std::list<std::pair<enum DwarfAttribute, enum DwarfForm> >
     AttributeList;
 typedef AttributeList::iterator AttributeIterator;
@@ -156,7 +157,7 @@
 
   // Called when we define a directory.  NAME is the directory name,
   // DIR_NUM is the directory number
-  virtual void DefineDir(const std::string& name, uint32 dir_num) { }
+  virtual void DefineDir(const string& name, uint32 dir_num) { }
 
   // Called when we define a filename. NAME is the filename, FILE_NUM
   // is the file number which is -1 if the file index is the next
@@ -165,7 +166,7 @@
   // directory index for the directory name of this file, MOD_TIME is
   // the modification time of the file, and LENGTH is the length of
   // the file
-  virtual void DefineFile(const std::string& name, int32 file_num,
+  virtual void DefineFile(const string& name, int32 file_num,
                           uint32 dir_num, uint64 mod_time,
                           uint64 length) { }
 
@@ -391,7 +392,7 @@
   virtual void ProcessAttributeString(uint64 offset,
                                       enum DwarfAttribute attr,
                                       enum DwarfForm form,
-                                      const std::string& data) { }
+                                      const string& data) { }
 
   // Called when we have an attribute whose value is the 64-bit signature
   // of a type unit in the .debug_types section. OFFSET is the offset of
@@ -699,7 +700,7 @@
   // A common information entry (CIE).
   struct CIE: public Entry {
     uint8 version;                      // CFI data version number
-    std::string augmentation;           // vendor format extension markers
+    string augmentation;                // vendor format extension markers
     uint64 code_alignment_factor;       // scale for code address adjustments 
     int data_alignment_factor;          // scale for stack pointer adjustments
     unsigned return_address_register;   // which register holds the return addr
@@ -833,7 +834,7 @@
   // process a given FDE, the parser reiterates the appropriate CIE's
   // contents at the beginning of the FDE's rules.
   virtual bool Entry(size_t offset, uint64 address, uint64 length,
-                     uint8 version, const std::string &augmentation,
+                     uint8 version, const string &augmentation,
                      unsigned return_address) = 0;
 
   // When the Entry function returns true, the parser calls these
@@ -882,13 +883,13 @@
   // At ADDRESS, the DWARF expression EXPRESSION yields the address at
   // which REG was saved.
   virtual bool ExpressionRule(uint64 address, int reg,
-                              const std::string &expression) = 0;
+                              const string &expression) = 0;
 
   // At ADDRESS, the DWARF expression EXPRESSION yields the caller's
   // value for REG. (This rule doesn't provide an address at which the
   // register's value is saved.)
   virtual bool ValExpressionRule(uint64 address, int reg,
-                                 const std::string &expression) = 0;
+                                 const string &expression) = 0;
 
   // Indicate that the rules for the address range reported by the
   // last call to Entry are complete.  End should return true if
@@ -965,8 +966,8 @@
   // in a Mach-O section named __debug_frame. If we support
   // Linux-style exception handling data, we could be reading an
   // .eh_frame section.
-  Reporter(const std::string &filename,
-           const std::string &section = ".debug_frame")
+  Reporter(const string &filename,
+           const string &section = ".debug_frame")
       : filename_(filename), section_(section) { }
   virtual ~Reporter() { }
 
@@ -998,7 +999,7 @@
   // which we don't recognize. We cannot parse DWARF CFI if it uses
   // augmentations we don't recognize.
   virtual void UnrecognizedAugmentation(uint64 offset,
-                                        const std::string &augmentation);
+                                        const string &augmentation);
 
   // The pointer encoding ENCODING, specified by the CIE at OFFSET, is not
   // a valid encoding.
@@ -1039,10 +1040,10 @@
 
  protected:
   // The name of the file whose CFI we're reading.
-  std::string filename_;
+  string filename_;
 
   // The name of the CFI section in that file.
-  std::string section_;
+  string section_;
 };
 
 }  // namespace dwarf2reader
diff --git a/src/common/dwarf/dwarf2reader_cfi_unittest.cc b/src/common/dwarf/dwarf2reader_cfi_unittest.cc
index 271d1b6..7b79436 100644
--- a/src/common/dwarf/dwarf2reader_cfi_unittest.cc
+++ b/src/common/dwarf/dwarf2reader_cfi_unittest.cc
@@ -62,6 +62,7 @@
 #include "common/dwarf/bytereader-inl.h"
 #include "common/dwarf/cfi_assembler.h"
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 using google_breakpad::CFISection;
@@ -76,7 +77,6 @@
 using dwarf2reader::ByteReader;
 using dwarf2reader::CallFrameInfo;
 
-using std::string;
 using std::vector;
 using testing::InSequence;
 using testing::Return;
diff --git a/src/common/dwarf/dwarf2reader_die_unittest.cc b/src/common/dwarf/dwarf2reader_die_unittest.cc
index e76fcae..96e95b7 100644
--- a/src/common/dwarf/dwarf2reader_die_unittest.cc
+++ b/src/common/dwarf/dwarf2reader_die_unittest.cc
@@ -41,6 +41,7 @@
 #include "common/dwarf/bytereader-inl.h"
 #include "common/dwarf/dwarf2reader_test_common.h"
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 using google_breakpad::test_assembler::Endianness;
@@ -61,7 +62,6 @@
 using dwarf2reader::ENDIANNESS_LITTLE;
 using dwarf2reader::SectionMap;
 
-using std::string;
 using std::vector;
 using testing::InSequence;
 using testing::Pointee;
@@ -98,7 +98,7 @@
   MOCK_METHOD4(ProcessAttributeString, void(uint64 offset,
                                             enum DwarfAttribute attr,
                                             enum DwarfForm form,
-                                            const std::string& data));
+                                            const string& data));
   MOCK_METHOD4(ProcessAttributeSignature, void(uint64 offset,
                                                DwarfAttribute attr,
                                                enum DwarfForm form,
diff --git a/src/common/dwarf/functioninfo.cc b/src/common/dwarf/functioninfo.cc
index 4a08045..c045622 100644
--- a/src/common/dwarf/functioninfo.cc
+++ b/src/common/dwarf/functioninfo.cc
@@ -39,14 +39,13 @@
 #include <memory>
 
 #include "common/dwarf/functioninfo.h"
-
 #include "common/dwarf/bytereader.h"
-
+#include "common/using_std_string.h"
 
 namespace dwarf2reader {
 
 CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
-                                     std::vector<std::string>* dirs,
+                                     std::vector<string>* dirs,
                                      LineMap* linemap):linemap_(linemap),
                                                        files_(files),
                                                        dirs_(dirs) {
@@ -61,13 +60,13 @@
   files->push_back(s);
 }
 
-void CULineInfoHandler::DefineDir(const std::string& name, uint32 dir_num) {
+void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) {
   // These should never come out of order, actually
   assert(dir_num == dirs_->size());
   dirs_->push_back(name);
 }
 
-void CULineInfoHandler::DefineFile(const std::string& name,
+void CULineInfoHandler::DefineFile(const string& name,
                                    int32 file_num, uint32 dir_num,
                                    uint64 mod_time, uint64 length) {
   assert(dir_num >= 0);
@@ -75,7 +74,7 @@
 
   // These should never come out of order, actually.
   if (file_num == (int32)files_->size() || file_num == -1) {
-    std::string dir = dirs_->at(dir_num);
+    string dir = dirs_->at(dir_num);
 
     SourceFileInfo s;
     s.lowpc = ULLONG_MAX;
@@ -149,7 +148,7 @@
 void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
                                                    enum DwarfAttribute attr,
                                                    enum DwarfForm form,
-                                                   const std::string &data) {
+                                                   const string &data) {
   if (current_function_info_) {
     if (attr == DW_AT_name)
       current_function_info_->name = data;
diff --git a/src/common/dwarf/functioninfo.h b/src/common/dwarf/functioninfo.h
index 85a31ff..f870636 100644
--- a/src/common/dwarf/functioninfo.h
+++ b/src/common/dwarf/functioninfo.h
@@ -40,17 +40,18 @@
 #include <vector>
 
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 
 
 namespace dwarf2reader {
 
 struct FunctionInfo {
   // Name of the function
-  std::string name;
+  string name;
   // Mangled name of the function
-  std::string mangled_name;
+  string mangled_name;
   // File containing this function
-  std::string file;
+  string file;
   // Line number for start of function.
   uint32 line;
   // Beginning address for this function
@@ -61,13 +62,13 @@
 
 struct SourceFileInfo {
   // Name of the source file name
-  std::string name;
+  string name;
   // Low address of source file name
   uint64 lowpc;
 };
 
 typedef std::map<uint64, FunctionInfo*> FunctionMap;
-typedef std::map<uint64, std::pair<std::string, uint32> > LineMap;
+typedef std::map<uint64, std::pair<string, uint32> > LineMap;
 
 // This class is a basic line info handler that fills in the dirs,
 // file, and linemap passed into it with the data produced from the
@@ -77,17 +78,17 @@
 
   //
   CULineInfoHandler(std::vector<SourceFileInfo>* files,
-                    std::vector<std::string>* dirs,
+                    std::vector<string>* dirs,
                     LineMap* linemap);
   virtual ~CULineInfoHandler() { }
 
   // Called when we define a directory.  We just place NAME into dirs_
   // at position DIR_NUM.
-  virtual void DefineDir(const std::string& name, uint32 dir_num);
+  virtual void DefineDir(const string& name, uint32 dir_num);
 
   // Called when we define a filename.  We just place
   // concat(dirs_[DIR_NUM], NAME) into files_ at position FILE_NUM.
-  virtual void DefineFile(const std::string& name, int32 file_num,
+  virtual void DefineFile(const string& name, int32 file_num,
                           uint32 dir_num, uint64 mod_time, uint64 length);
 
 
@@ -103,13 +104,13 @@
  private:
   LineMap* linemap_;
   std::vector<SourceFileInfo>* files_;
-  std::vector<std::string>* dirs_;
+  std::vector<string>* dirs_;
 };
 
 class CUFunctionInfoHandler: public Dwarf2Handler {
  public:
   CUFunctionInfoHandler(std::vector<SourceFileInfo>* files,
-                        std::vector<std::string>* dirs,
+                        std::vector<string>* dirs,
                         LineMap* linemap,
                         FunctionMap* offset_to_funcinfo,
                         FunctionMap* address_to_funcinfo,
@@ -163,7 +164,7 @@
   virtual void ProcessAttributeString(uint64 offset,
                                       enum DwarfAttribute attr,
                                       enum DwarfForm form,
-                                      const std::string& data);
+                                      const string& data);
 
   // Called when finished processing the DIE at OFFSET.
   // Because DWARF2/3 specifies a tree of DIEs, you may get starts
@@ -173,7 +174,7 @@
 
  private:
   std::vector<SourceFileInfo>* files_;
-  std::vector<std::string>* dirs_;
+  std::vector<string>* dirs_;
   LineMap* linemap_;
   FunctionMap* offset_to_funcinfo_;
   FunctionMap* address_to_funcinfo_;
diff --git a/src/common/dwarf_cfi_to_module.h b/src/common/dwarf_cfi_to_module.h
index d29a796..7db552a 100644
--- a/src/common/dwarf_cfi_to_module.h
+++ b/src/common/dwarf_cfi_to_module.h
@@ -48,13 +48,13 @@
 
 #include "common/module.h"
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
 using dwarf2reader::CallFrameInfo;
 using google_breakpad::Module;
 using std::set;
-using std::string;
 using std::vector;
 
 // A class that accepts parsed call frame information from the DWARF
diff --git a/src/common/dwarf_cfi_to_module_unittest.cc b/src/common/dwarf_cfi_to_module_unittest.cc
index 3d12949..bf3cf9a 100644
--- a/src/common/dwarf_cfi_to_module_unittest.cc
+++ b/src/common/dwarf_cfi_to_module_unittest.cc
@@ -36,8 +36,8 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/dwarf_cfi_to_module.h"
+#include "common/using_std_string.h"
 
-using std::string;
 using std::vector;
 
 using google_breakpad::Module;
diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc
index 2a8b76b..ded5f83 100644
--- a/src/common/dwarf_cu_to_module.cc
+++ b/src/common/dwarf_cu_to_module.cc
@@ -440,7 +440,11 @@
     func->address = low_pc_;
     func->size = high_pc_ - low_pc_;
     func->parameter_size = 0;
-    cu_context_->functions.push_back(func);
+    if (func->address) {
+       // If the function address is zero this is a sign that this function
+       // description is just empty debug data and should just be discarded.
+       cu_context_->functions.push_back(func);
+     }
   } else if (inline_) {
     AbstractOrigin origin(name_);
     cu_context_->file_context->file_private->origins[offset_] = origin;
@@ -553,7 +557,7 @@
 
 void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
   CUHeading();
-  fprintf(stderr, "%s: warning: function at offset 0x%" PRIx64 " has no name\n",
+  fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n",
           filename_.c_str(), offset);
 }
 
diff --git a/src/common/dwarf_cu_to_module.h b/src/common/dwarf_cu_to_module.h
index 9ab86a1..ac62846 100644
--- a/src/common/dwarf_cu_to_module.h
+++ b/src/common/dwarf_cu_to_module.h
@@ -46,6 +46,7 @@
 #include "common/dwarf/bytereader.h"
 #include "common/dwarf/dwarf2diehandler.h"
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
diff --git a/src/common/dwarf_cu_to_module_unittest.cc b/src/common/dwarf_cu_to_module_unittest.cc
index 03b0954..94259b6 100644
--- a/src/common/dwarf_cu_to_module_unittest.cc
+++ b/src/common/dwarf_cu_to_module_unittest.cc
@@ -37,9 +37,9 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/dwarf_cu_to_module.h"
+#include "common/using_std_string.h"
 
 using std::make_pair;
-using std::string;
 using std::vector;
 
 using dwarf2reader::AttributeList;
diff --git a/src/common/dwarf_line_to_module.cc b/src/common/dwarf_line_to_module.cc
index d987370..962848d 100644
--- a/src/common/dwarf_line_to_module.cc
+++ b/src/common/dwarf_line_to_module.cc
@@ -32,23 +32,26 @@
 // dwarf_line_to_module.cc: Implementation of DwarfLineToModule class.
 // See dwarf_line_to_module.h for details. 
 
-#include "common/dwarf_line_to_module.h"
-
 #include <stdio.h>
 
+#include <string>
+
+#include "common/dwarf_line_to_module.h"
+#include "common/using_std_string.h"
+
 // Trying to support Windows paths in a reasonable way adds a lot of
 // variations to test; it would be better to just put off dealing with
 // it until we actually have to deal with DWARF on Windows.
 
 // Return true if PATH is an absolute path, false if it is relative.
-static bool PathIsAbsolute(const std::string &path) {
+static bool PathIsAbsolute(const string &path) {
   return (path.size() >= 1 && path[0] == '/');
 }
 
 // If PATH is an absolute path, return PATH.  If PATH is a relative path,
 // treat it as relative to BASE and return the combined path.
-static std::string ExpandPath(const std::string &path,
-                              const std::string &base) {
+static string ExpandPath(const string &path,
+                         const string &base) {
   if (PathIsAbsolute(path))
     return path;
   return base + "/" + path;
@@ -56,14 +59,14 @@
 
 namespace google_breakpad {
 
-void DwarfLineToModule::DefineDir(const std::string &name, uint32 dir_num) {
+void DwarfLineToModule::DefineDir(const string &name, uint32 dir_num) {
   // Directory number zero is reserved to mean the compilation
   // directory. Silently ignore attempts to redefine it.
   if (dir_num != 0)
     directories_[dir_num] = name;
 }
 
-void DwarfLineToModule::DefineFile(const std::string &name, int32 file_num,
+void DwarfLineToModule::DefineFile(const string &name, int32 file_num,
                                    uint32 dir_num, uint64 mod_time,
                                    uint64 length) {
   if (file_num == -1)
@@ -71,7 +74,7 @@
   else if (file_num > highest_file_number_)
     highest_file_number_ = file_num;
 
-  std::string full_name;
+  string full_name;
   if (dir_num != 0) {
     DirectoryTable::const_iterator directory_it = directories_.find(dir_num);
     if (directory_it != directories_.end()) {
diff --git a/src/common/dwarf_line_to_module.h b/src/common/dwarf_line_to_module.h
index 49b3eb3..9382e40 100644
--- a/src/common/dwarf_line_to_module.h
+++ b/src/common/dwarf_line_to_module.h
@@ -38,8 +38,11 @@
 #ifndef COMMON_LINUX_DWARF_LINE_TO_MODULE_H
 #define COMMON_LINUX_DWARF_LINE_TO_MODULE_H
 
+#include <string>
+
 #include "common/module.h"
 #include "common/dwarf/dwarf2reader.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
@@ -127,8 +130,8 @@
   
   ~DwarfLineToModule() { }
 
-  void DefineDir(const std::string &name, uint32 dir_num);
-  void DefineFile(const std::string &name, int32 file_num,
+  void DefineDir(const string &name, uint32 dir_num);
+  void DefineFile(const string &name, int32 file_num,
                   uint32 dir_num, uint64 mod_time,
                   uint64 length);
   void AddLine(uint64 address, uint64 length,
@@ -136,7 +139,7 @@
 
  private:
 
-  typedef std::map<uint32, std::string> DirectoryTable;
+  typedef std::map<uint32, string> DirectoryTable;
   typedef std::map<uint32, Module::File *> FileTable;
 
   // The module we're contributing debugging info to. Owned by our
diff --git a/src/common/language.h b/src/common/language.h
index 03bdf7f..bbe3033 100644
--- a/src/common/language.h
+++ b/src/common/language.h
@@ -40,9 +40,9 @@
 
 #include <string>
 
-namespace google_breakpad {
+#include "common/using_std_string.h"
 
-using std::string;
+namespace google_breakpad {
 
 // An abstract base class for language-specific operations. We choose
 // an instance of a subclass of this when we find the CU's language.
@@ -50,6 +50,10 @@
 // language.
 class Language {
  public:
+  // A base class destructor should be either public and virtual,
+  // or protected and nonvirtual.
+  virtual ~Language() {}
+
   // Return true if this language has functions to which we can assign
   // line numbers. (Debugging info for assembly language, for example,
   // can have source location information, but does not have functions
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index f02503a..019a3a6 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -62,6 +62,7 @@
 #include "common/module.h"
 #include "common/stabs_reader.h"
 #include "common/stabs_to_module.h"
+#include "common/using_std_string.h"
 
 // This namespace contains helper functions.
 namespace {
@@ -235,7 +236,7 @@
   dwarf2reader::ByteReader *byte_reader_;
 };
 
-static bool LoadDwarf(const std::string &dwarf_filename,
+static bool LoadDwarf(const string &dwarf_filename,
                       const ElfW(Ehdr) *elf_header,
                       const bool big_endian,
                       Module *module) {
@@ -253,8 +254,8 @@
   const ElfW(Shdr) *section_names = sections + elf_header->e_shstrndx;
   for (int i = 0; i < num_sections; i++) {
     const ElfW(Shdr) *section = &sections[i];
-    std::string name = reinterpret_cast<const char *>(section_names->sh_offset +
-                                                      section->sh_name);
+    string name = reinterpret_cast<const char *>(section_names->sh_offset +
+                                                 section->sh_name);
     const char *contents = reinterpret_cast<const char *>(section->sh_offset);
     uint64 length = section->sh_size;
     file_context.section_map[name] = std::make_pair(contents, length);
@@ -292,7 +293,7 @@
 // success, or false if we don't recognize HEADER's machine
 // architecture.
 static bool DwarfCFIRegisterNames(const ElfW(Ehdr) *elf_header,
-                                  std::vector<std::string> *register_names) {
+                                  std::vector<string> *register_names) {
   switch (elf_header->e_machine) {
     case EM_386:
       *register_names = DwarfCFIToModule::RegisterNames::I386();
@@ -308,7 +309,7 @@
   }
 }
 
-static bool LoadDwarfCFI(const std::string &dwarf_filename,
+static bool LoadDwarfCFI(const string &dwarf_filename,
                          const ElfW(Ehdr) *elf_header,
                          const char *section_name,
                          const ElfW(Shdr) *section,
@@ -319,7 +320,7 @@
                          Module *module) {
   // Find the appropriate set of register names for this file's
   // architecture.
-  std::vector<std::string> register_names;
+  std::vector<string> register_names;
   if (!DwarfCFIRegisterNames(elf_header, &register_names)) {
     fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';"
             " cannot convert DWARF call frame information\n",
@@ -367,7 +368,7 @@
   return true;
 }
 
-bool LoadELF(const std::string &obj_file, MmapWrapper* map_wrapper,
+bool LoadELF(const string &obj_file, MmapWrapper* map_wrapper,
              ElfW(Ehdr) **elf_header) {
   int obj_fd = open(obj_file.c_str(), O_RDONLY);
   if (obj_fd < 0) {
@@ -416,9 +417,9 @@
 
 // Read the .gnu_debuglink and get the debug file name. If anything goes
 // wrong, return an empty string.
-static std::string ReadDebugLink(const ElfW(Shdr) *debuglink_section,
-                                 const std::string &obj_file,
-                                 const std::string &debug_dir) {
+static string ReadDebugLink(const ElfW(Shdr) *debuglink_section,
+                            const string &obj_file,
+                            const string &debug_dir) {
   char *debuglink = reinterpret_cast<char *>(debuglink_section->sh_offset);
   size_t debuglink_len = strlen(debuglink) + 5;  // '\0' + CRC32.
   debuglink_len = 4 * ((debuglink_len + 3) / 4);  // Round to nearest 4 bytes.
@@ -430,7 +431,7 @@
     return "";
   }
 
-  std::string debuglink_path = debug_dir + "/" + debuglink;
+  string debuglink_path = debug_dir + "/" + debuglink;
   int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
   if (debuglink_fd < 0) {
     fprintf(stderr, "Failed to open debug ELF file '%s' for '%s': %s\n",
@@ -453,13 +454,13 @@
 //
 class LoadSymbolsInfo {
  public:
-  explicit LoadSymbolsInfo(const std::string &dbg_dir) :
+  explicit LoadSymbolsInfo(const string &dbg_dir) :
     debug_dir_(dbg_dir),
     has_loading_addr_(false) {}
 
   // Keeps track of which sections have been loaded so we don't accidentally
   // load it twice from two different files.
-  void LoadedSection(const std::string &section) {
+  void LoadedSection(const string &section) {
     if (loaded_sections_.count(section) == 0) {
       loaded_sections_.insert(section);
     } else {
@@ -470,7 +471,7 @@
 
   // We expect the ELF file and linked debug file to have the same preferred
   // loading address.
-  void set_loading_addr(ElfW(Addr) addr, const std::string &filename) {
+  void set_loading_addr(ElfW(Addr) addr, const string &filename) {
     if (!has_loading_addr_) {
       loading_addr_ = addr;
       loaded_file_ = filename;
@@ -487,35 +488,35 @@
   }
 
   // Setters and getters
-  const std::string &debug_dir() const {
+  const string &debug_dir() const {
     return debug_dir_;
   }
 
-  std::string debuglink_file() const {
+  string debuglink_file() const {
     return debuglink_file_;
   }
-  void set_debuglink_file(std::string file) {
+  void set_debuglink_file(string file) {
     debuglink_file_ = file;
   }
 
  private:
-  const std::string &debug_dir_;  // Directory with the debug ELF file.
+  const string &debug_dir_;  // Directory with the debug ELF file.
 
-  std::string debuglink_file_;  // Full path to the debug ELF file.
+  string debuglink_file_;  // Full path to the debug ELF file.
 
   bool has_loading_addr_;  // Indicate if LOADING_ADDR_ is valid.
 
   ElfW(Addr) loading_addr_;  // Saves the preferred loading address from the
                              // first call to LoadSymbols().
 
-  std::string loaded_file_;  // Name of the file loaded from the first call to
+  string loaded_file_;  // Name of the file loaded from the first call to
                              // LoadSymbols().
 
-  std::set<std::string> loaded_sections_;  // Tracks the Loaded ELF sections
+  std::set<string> loaded_sections_;  // Tracks the Loaded ELF sections
                                            // between calls to LoadSymbols().
 };
 
-static bool LoadSymbols(const std::string &obj_file,
+static bool LoadSymbols(const string &obj_file,
                         const bool big_endian,
                         ElfW(Ehdr) *elf_header,
                         const bool read_gnu_debug_link,
@@ -615,7 +616,7 @@
                               elf_header->e_shnum);
       if (gnu_debuglink_section) {
         if (!info->debug_dir().empty()) {
-          std::string debuglink_file =
+          string debuglink_file =
               ReadDebugLink(gnu_debuglink_section, obj_file, info->debug_dir());
           info->set_debuglink_file(debuglink_file);
         } else {
@@ -690,13 +691,13 @@
 
 // Format the Elf file identifier in IDENTIFIER as a UUID with the
 // dashes removed.
-std::string FormatIdentifier(unsigned char identifier[16]) {
+string FormatIdentifier(unsigned char identifier[16]) {
   char identifier_str[40];
   google_breakpad::FileID::ConvertIdentifierToString(
       identifier,
       identifier_str,
       sizeof(identifier_str));
-  std::string id_no_dash;
+  string id_no_dash;
   for (int i = 0; identifier_str[i] != '\0'; ++i)
     if (identifier_str[i] != '-')
       id_no_dash += identifier_str[i];
@@ -710,10 +711,10 @@
 
 // Return the non-directory portion of FILENAME: the portion after the
 // last slash, or the whole filename if there are no slashes.
-std::string BaseFileName(const std::string &filename) {
+string BaseFileName(const string &filename) {
   // Lots of copies!  basename's behavior is less than ideal.
   char *c_filename = strdup(filename.c_str());
-  std::string base = basename(c_filename);
+  string base = basename(c_filename);
   free(c_filename);
   return base;
 }
@@ -726,8 +727,8 @@
 // Ideally obj_file would be const, but internally this code does write
 // to some ELF header fields to make its work simpler.
 bool WriteSymbolFileInternal(uint8_t* obj_file,
-                             const std::string &obj_filename,
-                             const std::string &debug_dir,
+                             const string &obj_filename,
+                             const string &debug_dir,
                              bool cfi,
                              std::ostream &sym_stream) {
   ElfW(Ehdr) *elf_header = reinterpret_cast<ElfW(Ehdr) *>(obj_file);
@@ -757,15 +758,15 @@
   if (!ElfEndianness(elf_header, &big_endian))
     return false;
 
-  std::string name = BaseFileName(obj_filename);
-  std::string os = "Linux";
-  std::string id = FormatIdentifier(identifier);
+  string name = BaseFileName(obj_filename);
+  string os = "Linux";
+  string id = FormatIdentifier(identifier);
 
   LoadSymbolsInfo info(debug_dir);
   Module module(name, os, architecture, id);
   if (!LoadSymbols(obj_filename, big_endian, elf_header, !debug_dir.empty(),
                    &info, &module)) {
-    const std::string debuglink_file = info.debuglink_file();
+    const string debuglink_file = info.debuglink_file();
     if (debuglink_file.empty())
       return false;
 
@@ -810,8 +811,8 @@
   return true;
 }
 
-bool WriteSymbolFile(const std::string &obj_file,
-                     const std::string &debug_dir,
+bool WriteSymbolFile(const string &obj_file,
+                     const string &debug_dir,
                      bool cfi,
                      std::ostream &sym_stream) {
   MmapWrapper map_wrapper;
diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h
index 9bf54d3..7b19281 100644
--- a/src/common/linux/dump_symbols.h
+++ b/src/common/linux/dump_symbols.h
@@ -38,6 +38,8 @@
 #include <iostream>
 #include <string>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
 // Find all the debugging information in OBJ_FILE, an ELF executable
@@ -46,8 +48,8 @@
 // If OBJ_FILE has been stripped but contains a .gnu_debuglink section,
 // then look for the debug file in DEBUG_DIR.
 // If CFI is set to false, then omit the CFI section.
-bool WriteSymbolFile(const std::string &obj_file,
-                     const std::string &debug_dir,
+bool WriteSymbolFile(const string &obj_file,
+                     const string &debug_dir,
                      bool cfi,
                      std::ostream &sym_stream);
 
diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc
index c6d4d2d..2c4f0e6 100644
--- a/src/common/linux/dump_symbols_unittest.cc
+++ b/src/common/linux/dump_symbols_unittest.cc
@@ -42,11 +42,12 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/linux/synth_elf.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 bool WriteSymbolFileInternal(uint8_t* obj_file,
-                             const std::string &obj_filename,
-                             const std::string &debug_dir,
+                             const string &obj_filename,
+                             const string &debug_dir,
                              bool cfi,
                              std::ostream &sym_stream);
 }
@@ -57,7 +58,6 @@
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Section;
 using google_breakpad::WriteSymbolFileInternal;
-using std::string;
 using std::stringstream;
 using std::vector;
 using ::testing::Test;
diff --git a/src/common/linux/elf_core_dump_unittest.cc b/src/common/linux/elf_core_dump_unittest.cc
index 11920f2..ce0ab54 100644
--- a/src/common/linux/elf_core_dump_unittest.cc
+++ b/src/common/linux/elf_core_dump_unittest.cc
@@ -39,6 +39,7 @@
 #include "common/linux/memory_mapped_file.h"
 #include "common/tests/file_utils.h"
 #include "common/linux/tests/crash_generator.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::AutoTempDir;
 using google_breakpad::CrashGenerator;
@@ -47,7 +48,6 @@
 using google_breakpad::MemoryRange;
 using google_breakpad::WriteFile;
 using std::set;
-using std::string;
 
 TEST(ElfCoreDumpTest, DefaultConstructor) {
   ElfCoreDump core;
@@ -182,8 +182,12 @@
 
   size_t num_nt_prpsinfo = 0;
   size_t num_nt_prstatus = 0;
+#if defined(__i386__) || defined(__x86_64__)
   size_t num_nt_fpregset = 0;
+#endif
+#if defined(__i386__)
   size_t num_nt_prxfpreg = 0;
+#endif
   set<pid_t> actual_thread_ids;
   ElfCoreDump::Note note = core.GetFirstNote();
   while (note.IsValid()) {
@@ -211,7 +215,7 @@
         ++num_nt_prstatus;
         break;
       }
-#if defined(__i386) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
       case NT_FPREGSET: {
         EXPECT_TRUE(description.data() != NULL);
         EXPECT_EQ(sizeof(user_fpregs_struct), description.length());
@@ -219,7 +223,7 @@
         break;
       }
 #endif
-#if defined(__i386)
+#if defined(__i386__)
       case NT_PRXFPREG: {
         EXPECT_TRUE(description.data() != NULL);
         EXPECT_EQ(sizeof(user_fpxregs_struct), description.length());
@@ -236,10 +240,10 @@
   EXPECT_TRUE(expected_thread_ids == actual_thread_ids);
   EXPECT_EQ(1, num_nt_prpsinfo);
   EXPECT_EQ(kNumOfThreads, num_nt_prstatus);
-#if defined(__i386) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
   EXPECT_EQ(kNumOfThreads, num_nt_fpregset);
 #endif
-#if defined(__i386)
+#if defined(__i386__)
   EXPECT_EQ(kNumOfThreads, num_nt_prxfpreg);
 #endif
 }
diff --git a/src/common/linux/elf_symbols_to_module_unittest.cc b/src/common/linux/elf_symbols_to_module_unittest.cc
index a3b874f..8984449 100644
--- a/src/common/linux/elf_symbols_to_module_unittest.cc
+++ b/src/common/linux/elf_symbols_to_module_unittest.cc
@@ -42,6 +42,7 @@
 #include "common/linux/synth_elf.h"
 #include "common/module.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::Module;
 using google_breakpad::synth_elf::StringTable;
@@ -52,7 +53,6 @@
 using google_breakpad::test_assembler::Section;
 using ::testing::Test;
 using ::testing::TestWithParam;
-using std::string;
 using std::vector;
 
 class ELFSymbolsToModuleTestFixture {
diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc
index bffef62..ff2f29e 100644
--- a/src/common/linux/file_id.cc
+++ b/src/common/linux/file_id.cc
@@ -36,10 +36,11 @@
 
 #include <arpa/inet.h>
 #include <assert.h>
-#include <elf.h>
 #if defined(__ANDROID__)
+#include <linux/elf.h>
 #include "client/linux/android_link.h"
 #else
+#include <elf.h>
 #include <link.h>
 #endif
 #include <string.h>
diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc
index 94bc80e..daef1e3 100644
--- a/src/common/linux/file_id_unittest.cc
+++ b/src/common/linux/file_id_unittest.cc
@@ -32,11 +32,14 @@
 #include <elf.h>
 #include <stdlib.h>
 
+#include <string>
+
 #include "common/linux/file_id.h"
 #include "common/linux/safe_readlink.h"
 #include "common/linux/synth_elf.h"
 #include "common/test_assembler.h"
 #include "common/tests/auto_tempdir.h"
+#include "common/using_std_string.h"
 #include "breakpad_googletest_includes.h"
 
 using namespace google_breakpad;
@@ -67,12 +70,14 @@
 
   // copy our binary to a temp file, and strip it
   AutoTempDir temp_dir;
-  std::string templ = temp_dir.path() + "/file-id-unittest";
+  string templ = temp_dir.path() + "/file-id-unittest";
   char cmdline[4096];
   sprintf(cmdline, "cp \"%s\" \"%s\"", exe_name, templ.c_str());
-  ASSERT_EQ(system(cmdline), 0);
+  ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
+  sprintf(cmdline, "chmod u+w \"%s\"", templ.c_str());
+  ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
   sprintf(cmdline, "strip \"%s\"", templ.c_str());
-  ASSERT_EQ(system(cmdline), 0);
+  ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
 
   uint8_t identifier1[sizeof(MDGUID)];
   uint8_t identifier2[sizeof(MDGUID)];
diff --git a/src/common/linux/google_crashdump_uploader.cc b/src/common/linux/google_crashdump_uploader.cc
index b739a6f..b5f32c6 100644
--- a/src/common/linux/google_crashdump_uploader.cc
+++ b/src/common/linux/google_crashdump_uploader.cc
@@ -37,21 +37,21 @@
 
 #include <iostream>
 
-using std::string;
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
-GoogleCrashdumpUploader::GoogleCrashdumpUploader(const std::string& product,
-                                                 const std::string& version,
-                                                 const std::string& guid,
-                                                 const std::string& ptime,
-                                                 const std::string& ctime,
-                                                 const std::string& email,
-                                                 const std::string& comments,
-                                                 const std::string& minidump_pathname,
-                                                 const std::string& crash_server,
-                                                 const std::string& proxy_host,
-                                                 const std::string& proxy_userpassword) {
+GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
+                                                 const string& version,
+                                                 const string& guid,
+                                                 const string& ptime,
+                                                 const string& ctime,
+                                                 const string& email,
+                                                 const string& comments,
+                                                 const string& minidump_pathname,
+                                                 const string& crash_server,
+                                                 const string& proxy_host,
+                                                 const string& proxy_userpassword) {
   LibcurlWrapper* http_layer = new LibcurlWrapper();
   Init(product,
        version,
@@ -67,17 +67,17 @@
        http_layer);
 }
 
-GoogleCrashdumpUploader::GoogleCrashdumpUploader(const std::string& product,
-                                                 const std::string& version,
-                                                 const std::string& guid,
-                                                 const std::string& ptime,
-                                                 const std::string& ctime,
-                                                 const std::string& email,
-                                                 const std::string& comments,
-                                                 const std::string& minidump_pathname,
-                                                 const std::string& crash_server,
-                                                 const std::string& proxy_host,
-                                                 const std::string& proxy_userpassword,
+GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
+                                                 const string& version,
+                                                 const string& guid,
+                                                 const string& ptime,
+                                                 const string& ctime,
+                                                 const string& email,
+                                                 const string& comments,
+                                                 const string& minidump_pathname,
+                                                 const string& crash_server,
+                                                 const string& proxy_host,
+                                                 const string& proxy_userpassword,
                                                  LibcurlWrapper* http_layer) {
   Init(product,
        version,
@@ -93,17 +93,17 @@
        http_layer);
 }
 
-void GoogleCrashdumpUploader::Init(const std::string& product,
-                                   const std::string& version,
-                                   const std::string& guid,
-                                   const std::string& ptime,
-                                   const std::string& ctime,
-                                   const std::string& email,
-                                   const std::string& comments,
-                                   const std::string& minidump_pathname,
-                                   const std::string& crash_server,
-                                   const std::string& proxy_host,
-                                   const std::string& proxy_userpassword,
+void GoogleCrashdumpUploader::Init(const string& product,
+                                   const string& version,
+                                   const string& guid,
+                                   const string& ptime,
+                                   const string& ctime,
+                                   const string& email,
+                                   const string& comments,
+                                   const string& minidump_pathname,
+                                   const string& crash_server,
+                                   const string& proxy_host,
+                                   const string& proxy_userpassword,
                                    LibcurlWrapper* http_layer) {
   product_ = product;
   version_ = version;
@@ -137,7 +137,7 @@
 }
 
 bool GoogleCrashdumpUploader::CheckRequiredParametersArePresent() {
-  std::string error_text;
+  string error_text;
   if (product_.empty()) {
     error_text.append("\nProduct name must be specified.");
   }
diff --git a/src/common/linux/google_crashdump_uploader.h b/src/common/linux/google_crashdump_uploader.h
index 5cea17d..5eef28b 100644
--- a/src/common/linux/google_crashdump_uploader.h
+++ b/src/common/linux/google_crashdump_uploader.h
@@ -31,48 +31,50 @@
 #include <string>
 #include <map>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
 class LibcurlWrapper;
 
 class GoogleCrashdumpUploader {
  public:
-  GoogleCrashdumpUploader(const std::string& product,
-                          const std::string& version,
-                          const std::string& guid,
-                          const std::string& ptime,
-                          const std::string& ctime,
-                          const std::string& email,
-                          const std::string& comments,
-                          const std::string& minidump_pathname,
-                          const std::string& crash_server,
-                          const std::string& proxy_host,
-                          const std::string& proxy_userpassword);
+  GoogleCrashdumpUploader(const string& product,
+                          const string& version,
+                          const string& guid,
+                          const string& ptime,
+                          const string& ctime,
+                          const string& email,
+                          const string& comments,
+                          const string& minidump_pathname,
+                          const string& crash_server,
+                          const string& proxy_host,
+                          const string& proxy_userpassword);
 
-  GoogleCrashdumpUploader(const std::string& product,
-                          const std::string& version,
-                          const std::string& guid,
-                          const std::string& ptime,
-                          const std::string& ctime,
-                          const std::string& email,
-                          const std::string& comments,
-                          const std::string& minidump_pathname,
-                          const std::string& crash_server,
-                          const std::string& proxy_host,
-                          const std::string& proxy_userpassword,
+  GoogleCrashdumpUploader(const string& product,
+                          const string& version,
+                          const string& guid,
+                          const string& ptime,
+                          const string& ctime,
+                          const string& email,
+                          const string& comments,
+                          const string& minidump_pathname,
+                          const string& crash_server,
+                          const string& proxy_host,
+                          const string& proxy_userpassword,
                           LibcurlWrapper* http_layer);
 
-  void Init(const std::string& product,
-            const std::string& version,
-            const std::string& guid,
-            const std::string& ptime,
-            const std::string& ctime,
-            const std::string& email,
-            const std::string& comments,
-            const std::string& minidump_pathname,
-            const std::string& crash_server,
-            const std::string& proxy_host,
-            const std::string& proxy_userpassword,
+  void Init(const string& product,
+            const string& version,
+            const string& guid,
+            const string& ptime,
+            const string& ctime,
+            const string& email,
+            const string& comments,
+            const string& minidump_pathname,
+            const string& crash_server,
+            const string& proxy_host,
+            const string& proxy_userpassword,
             LibcurlWrapper* http_layer);
   bool Upload();
 
@@ -80,19 +82,19 @@
   bool CheckRequiredParametersArePresent();
 
   LibcurlWrapper* http_layer_;
-  std::string product_;
-  std::string version_;
-  std::string guid_;
-  std::string ptime_;
-  std::string ctime_;
-  std::string email_;
-  std::string comments_;
-  std::string minidump_pathname_;
+  string product_;
+  string version_;
+  string guid_;
+  string ptime_;
+  string ctime_;
+  string email_;
+  string comments_;
+  string minidump_pathname_;
 
-  std::string crash_server_;
-  std::string proxy_host_;
-  std::string proxy_userpassword_;
+  string crash_server_;
+  string proxy_host_;
+  string proxy_userpassword_;
 
-  std::map<std::string, std::string> parameters_;
+  std::map<string, string> parameters_;
 };
 }
diff --git a/src/common/linux/google_crashdump_uploader_test.cc b/src/common/linux/google_crashdump_uploader_test.cc
index c65355c..957874a 100644
--- a/src/common/linux/google_crashdump_uploader_test.cc
+++ b/src/common/linux/google_crashdump_uploader_test.cc
@@ -29,9 +29,12 @@
 
 // Unit test for crash dump uploader.
 
+#include <string>
+
 #include "common/linux/google_crashdump_uploader.h"
 #include "common/linux/libcurl_wrapper.h"
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
@@ -41,14 +44,14 @@
 class MockLibcurlWrapper : public LibcurlWrapper {
  public:
   MOCK_METHOD0(Init, bool());
-  MOCK_METHOD2(SetProxy, bool(const std::string& proxy_host,
-                              const std::string& proxy_userpwd));
-  MOCK_METHOD2(AddFile, bool(const std::string& upload_file_path,
-                             const std::string& basename));
+  MOCK_METHOD2(SetProxy, bool(const string& proxy_host,
+                              const string& proxy_userpwd));
+  MOCK_METHOD2(AddFile, bool(const string& upload_file_path,
+                             const string& basename));
   MOCK_METHOD3(SendRequest,
-               bool(const std::string& url,
-                    const std::map<std::string, std::string>& parameters,
-                    std::string* server_response));
+               bool(const string& url,
+                    const std::map<string, string>& parameters,
+                    string* server_response));
 };
 
 class GoogleCrashdumpUploaderTest : public ::testing::Test {
diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc
index f69237c..fead76e 100644
--- a/src/common/linux/http_upload.cc
+++ b/src/common/linux/http_upload.cc
@@ -41,7 +41,7 @@
   if (!userp)
     return 0;
 
-  std::string *response = reinterpret_cast<std::string *>(userp);
+  string *response = reinterpret_cast<string *>(userp);
   size_t real_size = size * nmemb;
   response->append(reinterpret_cast<char *>(ptr), real_size);
   return real_size;
diff --git a/src/common/linux/http_upload.h b/src/common/linux/http_upload.h
index 22b6296..6dd36ea 100644
--- a/src/common/linux/http_upload.h
+++ b/src/common/linux/http_upload.h
@@ -37,9 +37,10 @@
 #include <map>
 #include <string>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
-using std::string;
 using std::map;
 
 class HTTPUpload {
diff --git a/src/common/linux/libcurl_wrapper.cc b/src/common/linux/libcurl_wrapper.cc
index 8b61aa0..08307f0 100644
--- a/src/common/linux/libcurl_wrapper.cc
+++ b/src/common/linux/libcurl_wrapper.cc
@@ -33,8 +33,7 @@
 #include <string>
 
 #include "common/linux/libcurl_wrapper.h"
-
-using std::string;
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 LibcurlWrapper::LibcurlWrapper()
@@ -58,8 +57,8 @@
   return;
 }
 
-bool LibcurlWrapper::SetProxy(const std::string& proxy_host,
-                              const std::string& proxy_userpwd) {
+bool LibcurlWrapper::SetProxy(const string& proxy_host,
+                              const string& proxy_userpwd) {
   if (!init_ok_) {
     return false;
   }
@@ -80,8 +79,8 @@
   return true;
 }
 
-bool LibcurlWrapper::AddFile(const std::string& upload_file_path,
-                             const std::string& basename) {
+bool LibcurlWrapper::AddFile(const string& upload_file_path,
+                             const string& basename) {
   if (!init_ok_) {
     return false;
   }
@@ -101,17 +100,17 @@
   if (!userp)
     return 0;
 
-  std::string *response = reinterpret_cast<std::string *>(userp);
+  string *response = reinterpret_cast<string *>(userp);
   size_t real_size = size * nmemb;
   response->append(reinterpret_cast<char *>(ptr), real_size);
   return real_size;
 }
 
-bool LibcurlWrapper::SendRequest(const std::string& url,
-                                 const std::map<std::string, std::string>& parameters,
-                                 std::string* server_response) {
+bool LibcurlWrapper::SendRequest(const string& url,
+                                 const std::map<string, string>& parameters,
+                                 string* server_response) {
   (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str());
-  std::map<std::string, std::string>::const_iterator iter = parameters.begin();
+  std::map<string, string>::const_iterator iter = parameters.begin();
   for (; iter != parameters.end(); ++iter)
     (*formadd_)(&formpost_, &lastptr_,
                 CURLFORM_COPYNAME, iter->first.c_str(),
diff --git a/src/common/linux/libcurl_wrapper.h b/src/common/linux/libcurl_wrapper.h
index 3e53e61..3b72b5e 100644
--- a/src/common/linux/libcurl_wrapper.h
+++ b/src/common/linux/libcurl_wrapper.h
@@ -33,6 +33,7 @@
 #include <string>
 #include <map>
 
+#include "common/using_std_string.h"
 #include "third_party/curl/curl.h"
 
 namespace google_breakpad {
@@ -40,13 +41,13 @@
  public:
   LibcurlWrapper();
   virtual bool Init();
-  virtual bool SetProxy(const std::string& proxy_host,
-                        const std::string& proxy_userpwd);
-  virtual bool AddFile(const std::string& upload_file_path,
-                       const std::string& basename);
-  virtual bool SendRequest(const std::string& url,
-                           const std::map<std::string, std::string>& parameters,
-                           std::string* server_response);
+  virtual bool SetProxy(const string& proxy_host,
+                        const string& proxy_userpwd);
+  virtual bool AddFile(const string& upload_file_path,
+                       const string& basename);
+  virtual bool SendRequest(const string& url,
+                           const std::map<string, string>& parameters,
+                           string* server_response);
  private:
   // This function initializes class state corresponding to function
   // pointers into the CURL library.
@@ -55,7 +56,7 @@
   bool init_ok_;                 // Whether init succeeded
   void* curl_lib_;               // Pointer to result of dlopen() on
                                  // curl library
-  std::string last_curl_error_;  // The text of the last error when
+  string last_curl_error_;  // The text of the last error when
                                  // dealing
   // with CURL.
 
diff --git a/src/common/linux/linux_libc_support_unittest.cc b/src/common/linux/linux_libc_support_unittest.cc
index a7c5a26..6f4b2da 100644
--- a/src/common/linux/linux_libc_support_unittest.cc
+++ b/src/common/linux/linux_libc_support_unittest.cc
@@ -27,8 +27,8 @@
 // (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 "breakpad_googletest_includes.h"
 #include "common/linux/linux_libc_support.h"
-#include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 typedef testing::Test LinuxLibcSupportTest;
diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc
index 6f450bd..32fc3b1 100644
--- a/src/common/linux/memory_mapped_file.cc
+++ b/src/common/linux/memory_mapped_file.cc
@@ -34,6 +34,9 @@
 
 #include <fcntl.h>
 #include <sys/mman.h>
+#if defined(__ANDROID__)
+#include <sys/stat.h>
+#endif
 #include <unistd.h>
 
 #include "common/memory_range.h"
@@ -59,7 +62,10 @@
     return false;
   }
 
-#if defined(__x86_64__)
+#if defined(__ANDROID__)
+  struct stat st;
+  if (fstat(fd, &st) != 0) {
+#elif defined(__x86_64__)
   struct kernel_stat st;
   if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
 #else
diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc
index cf89bca..0c551ac 100644
--- a/src/common/linux/memory_mapped_file_unittest.cc
+++ b/src/common/linux/memory_mapped_file_unittest.cc
@@ -41,11 +41,11 @@
 #include "common/linux/memory_mapped_file.h"
 #include "common/tests/auto_tempdir.h"
 #include "common/tests/file_utils.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::AutoTempDir;
 using google_breakpad::MemoryMappedFile;
 using google_breakpad::WriteFile;
-using std::string;
 
 namespace {
 
diff --git a/src/common/linux/synth_elf.cc b/src/common/linux/synth_elf.cc
index 3e10b69..afaea02 100644
--- a/src/common/linux/synth_elf.cc
+++ b/src/common/linux/synth_elf.cc
@@ -5,6 +5,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 namespace synth_elf {
 
diff --git a/src/common/linux/synth_elf.h b/src/common/linux/synth_elf.h
index 90bd834..1fbe749 100644
--- a/src/common/linux/synth_elf.h
+++ b/src/common/linux/synth_elf.h
@@ -43,13 +43,14 @@
 #include <string>
 #include <utility>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 namespace synth_elf {
 
 using std::list;
 using std::map;
 using std::pair;
-using std::string;
 using test_assembler::Endianness;
 using test_assembler::kLittleEndian;
 using test_assembler::kUnsetEndian;
diff --git a/src/common/linux/synth_elf_unittest.cc b/src/common/linux/synth_elf_unittest.cc
index 8cc7ad2..0cb7d27 100644
--- a/src/common/linux/synth_elf_unittest.cc
+++ b/src/common/linux/synth_elf_unittest.cc
@@ -36,6 +36,7 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/linux/synth_elf.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::synth_elf::ELF;
 using google_breakpad::synth_elf::StringTable;
@@ -44,7 +45,6 @@
 using google_breakpad::test_assembler::kBigEndian;
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Label;
-using std::string;
 using ::testing::Test;
 
 class StringTableTest : public Test {
diff --git a/src/common/linux/tests/crash_generator.cc b/src/common/linux/tests/crash_generator.cc
index dff2bca..c78b793 100644
--- a/src/common/linux/tests/crash_generator.cc
+++ b/src/common/linux/tests/crash_generator.cc
@@ -46,6 +46,7 @@
 #include "common/linux/eintr_wrapper.h"
 #include "common/tests/auto_tempdir.h"
 #include "common/tests/file_utils.h"
+#include "common/using_std_string.h"
 
 namespace {
 
@@ -97,11 +98,11 @@
          buffer_size == 5 && memcmp(buffer, "core", 4) == 0;
 }
 
-std::string CrashGenerator::GetCoreFilePath() const {
+string CrashGenerator::GetCoreFilePath() const {
   return temp_dir_.path() + "/core";
 }
 
-std::string CrashGenerator::GetDirectoryOfProcFilesCopy() const {
+string CrashGenerator::GetDirectoryOfProcFilesCopy() const {
   return temp_dir_.path() + "/proc";
 }
 
@@ -170,7 +171,7 @@
     }
     if (SetCoreFileSizeLimit(kCoreSizeLimit)) {
       CreateThreadsInChildProcess(num_threads);
-      std::string proc_dir = GetDirectoryOfProcFilesCopy();
+      string proc_dir = GetDirectoryOfProcFilesCopy();
       if (mkdir(proc_dir.c_str(), 0755) == -1) {
         perror("CrashGenerator: Failed to create proc directory");
         exit(1);
@@ -195,7 +196,10 @@
     return false;
   }
   if (!WIFSIGNALED(status) || WTERMSIG(status) != crash_signal) {
-    perror("CrashGenerator: Child process not killed by the expected signal");
+    fprintf(stderr, "CrashGenerator: Child process not killed by the expected signal\n"
+                    "  exit status=0x%x signaled=%s sig=%d expected=%d\n",
+                    status, WIFSIGNALED(status) ? "true" : "false",
+                    WTERMSIG(status), crash_signal);
     return false;
   }
 
diff --git a/src/common/linux/tests/crash_generator.h b/src/common/linux/tests/crash_generator.h
index d05ce73..7e2fcbf 100644
--- a/src/common/linux/tests/crash_generator.h
+++ b/src/common/linux/tests/crash_generator.h
@@ -38,6 +38,7 @@
 #include <string>
 
 #include "common/tests/auto_tempdir.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
@@ -59,10 +60,10 @@
   bool HasDefaultCorePattern() const;
 
   // Returns the expected path of the core dump file.
-  std::string GetCoreFilePath() const;
+  string GetCoreFilePath() const;
 
   // Returns the directory of a copy of proc files of the child process.
-  std::string GetDirectoryOfProcFilesCopy() const;
+  string GetDirectoryOfProcFilesCopy() const;
 
   // Creates a crash (and a core dump file) by creating a child process with
   // |num_threads| threads, and the terminating the child process by sending
diff --git a/src/common/mac/HTTPMultipartUpload.m b/src/common/mac/HTTPMultipartUpload.m
index 1316b8e..76f38f8 100644
--- a/src/common/mac/HTTPMultipartUpload.m
+++ b/src/common/mac/HTTPMultipartUpload.m
@@ -32,6 +32,8 @@
 
 @interface HTTPMultipartUpload(PrivateMethods)
 - (NSString *)multipartBoundary;
+// Each of the following methods will append the starting multipart boundary,
+// but not the ending one.
 - (NSData *)formDataForKey:(NSString *)key value:(NSString *)value;
 - (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name;
 - (NSData *)formDataForFile:(NSString *)file name:(NSString *)name;
@@ -67,11 +69,9 @@
   NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; "
     "filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n";
   NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped];
-  NSString *post = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_];
 
   [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]];
   [data appendData:contents];
-  [data appendData:[post dataUsingEncoding:NSUTF8StringEncoding]];
 
   return data;
 }
@@ -182,6 +182,9 @@
     [postBody appendData:fileData];
   }
 
+  NSString *epilogue = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_];
+  [postBody appendData:[epilogue dataUsingEncoding:NSUTF8StringEncoding]];
+
   [req setHTTPBody:postBody];
   [req setHTTPMethod:@"POST"];
 
diff --git a/src/common/memory_unittest.cc b/src/common/memory_unittest.cc
index d580c1f..69d9f8a 100644
--- a/src/common/memory_unittest.cc
+++ b/src/common/memory_unittest.cc
@@ -27,8 +27,8 @@
 // (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 "breakpad_googletest_includes.h"
 #include "common/memory.h"
-#include "testing/gtest/include/gtest/gtest.h"
 
 using namespace google_breakpad;
 
diff --git a/src/common/module.h b/src/common/module.h
index 734a1af..cc89bba 100644
--- a/src/common/module.h
+++ b/src/common/module.h
@@ -44,12 +44,12 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
 
 using std::set;
-using std::string;
 using std::vector;
 using std::map;
 
diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
index 85c3b1c..04dc404 100644
--- a/src/common/module_unittest.cc
+++ b/src/common/module_unittest.cc
@@ -42,9 +42,9 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/module.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::Module;
-using std::string;
 using std::stringstream;
 using std::vector;
 using testing::ContainerEq;
diff --git a/src/common/stabs_reader.cc b/src/common/stabs_reader.cc
index 4897361..6019fc7 100644
--- a/src/common/stabs_reader.cc
+++ b/src/common/stabs_reader.cc
@@ -37,6 +37,10 @@
 #include <stab.h>
 #include <string.h>
 
+#include <string>
+
+#include "common/using_std_string.h"
+
 using std::vector;
 
 namespace google_breakpad {
@@ -225,7 +229,7 @@
   const char *name_end = strchr(stab_string, ':');
   if (! name_end)
     name_end = stab_string + strlen(stab_string);
-  std::string name(stab_string, name_end - stab_string);
+  string name(stab_string, name_end - stab_string);
   if (! handler_->StartFunction(name, function_address))
     return false;
   ++iterator_;
diff --git a/src/common/stabs_reader.h b/src/common/stabs_reader.h
index b22ebfd..d89afc0 100644
--- a/src/common/stabs_reader.h
+++ b/src/common/stabs_reader.h
@@ -64,6 +64,7 @@
 #include <vector>
 
 #include "common/byte_cursor.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
@@ -292,7 +293,7 @@
   // StartFunction is the function name alone.
   //
   // In languages that use name mangling, like C++, NAME is mangled.
-  virtual bool StartFunction(const std::string &name, uint64_t address) {
+  virtual bool StartFunction(const string &name, uint64_t address) {
     return true;
   }
 
@@ -311,7 +312,7 @@
 
   // Report that an exported function NAME is present at ADDRESS.
   // The size of the function is unknown.
-  virtual bool Extern(const std::string &name, uint64_t address) {
+  virtual bool Extern(const string &name, uint64_t address) {
     return true;
   }
 
diff --git a/src/common/stabs_reader_unittest.cc b/src/common/stabs_reader_unittest.cc
index 2a9b5d4..35d5e6c 100644
--- a/src/common/stabs_reader_unittest.cc
+++ b/src/common/stabs_reader_unittest.cc
@@ -43,10 +43,12 @@
 #include <iostream>
 #include <map>
 #include <sstream>
+#include <string>
 
 #include "breakpad_googletest_includes.h"
 #include "common/stabs_reader.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 
 using ::testing::Eq;
 using ::testing::InSequence;
@@ -61,7 +63,6 @@
 using google_breakpad::test_assembler::kBigEndian;
 using google_breakpad::test_assembler::kLittleEndian;
 using std::map;
-using std::string;
 
 namespace {
 
@@ -218,10 +219,10 @@
   MOCK_METHOD3(StartCompilationUnit,
                bool(const char *, uint64_t, const char *));
   MOCK_METHOD1(EndCompilationUnit, bool(uint64_t));
-  MOCK_METHOD2(StartFunction, bool(const std::string &, uint64_t));
+  MOCK_METHOD2(StartFunction, bool(const string &, uint64_t));
   MOCK_METHOD1(EndFunction, bool(uint64_t));
   MOCK_METHOD3(Line, bool(uint64_t, const char *, int));
-  MOCK_METHOD2(Extern, bool(const std::string &, uint64_t));
+  MOCK_METHOD2(Extern, bool(const string &, uint64_t));
   void Warning(const char *format, ...) { MockWarning(format); }
   MOCK_METHOD1(MockWarning, void(const char *));
 };
diff --git a/src/common/stabs_to_module.cc b/src/common/stabs_to_module.cc
index 67cd13b..e59aebd 100644
--- a/src/common/stabs_to_module.cc
+++ b/src/common/stabs_to_module.cc
@@ -39,11 +39,10 @@
 #include <algorithm>
 
 #include "common/stabs_to_module.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
-using std::string;
-
 // Demangle using abi call.
 // Older GCC may not support it.
 static string Demangle(const string &mangled) {
diff --git a/src/common/stabs_to_module.h b/src/common/stabs_to_module.h
index 632f4d0..5e04fa7 100644
--- a/src/common/stabs_to_module.h
+++ b/src/common/stabs_to_module.h
@@ -45,10 +45,10 @@
 
 #include "common/module.h"
 #include "common/stabs_reader.h"
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
-using std::string;
 using std::vector;
 
 // A StabsToModule is a handler that receives parsed STABS debugging 
diff --git a/src/common/string_conversion.cc b/src/common/string_conversion.cc
index 5af12f5..27fb8cd 100644
--- a/src/common/string_conversion.cc
+++ b/src/common/string_conversion.cc
@@ -27,14 +27,15 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "common/convert_UTF.h"
-#include "processor/scoped_ptr.h"
-#include "common/string_conversion.h"
 #include <string.h>
 
+#include "common/convert_UTF.h"
+#include "common/string_conversion.h"
+#include "common/using_std_string.h"
+#include "processor/scoped_ptr.h"
+
 namespace google_breakpad {
 
-using std::string;
 using std::vector;
 
 void UTF8ToUTF16(const char *in, vector<u_int16_t> *out) {
@@ -42,7 +43,7 @@
   const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
   const UTF8 *source_end_ptr = source_ptr + source_length;
   // Erase the contents and zero fill to the expected size
-  out->empty();
+  out->clear();
   out->insert(out->begin(), source_length, 0);
   u_int16_t *target_ptr = &(*out)[0];
   u_int16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(u_int16_t);
@@ -86,7 +87,7 @@
   const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(in);
   const UTF32 *source_end_ptr = source_ptr + source_length;
   // Erase the contents and zero fill to the expected size
-  out->empty();
+  out->clear();
   out->insert(out->begin(), source_length, 0);
   u_int16_t *target_ptr = &(*out)[0];
   u_int16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(u_int16_t);
diff --git a/src/common/string_conversion.h b/src/common/string_conversion.h
index d51f46b..eeed4d2 100644
--- a/src/common/string_conversion.h
+++ b/src/common/string_conversion.h
@@ -34,6 +34,8 @@
 
 #include <string>
 #include <vector>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
@@ -59,7 +61,7 @@
 void UTF32ToUTF16Char(wchar_t in, u_int16_t out[2]);
 
 // Convert |in| to UTF-8.  If |swap| is true, swap bytes before converting.
-std::string UTF16ToUTF8(const vector<u_int16_t> &in, bool swap);
+string UTF16ToUTF8(const vector<u_int16_t> &in, bool swap);
 
 }  // namespace google_breakpad
 
diff --git a/src/common/test_assembler.h b/src/common/test_assembler.h
index 5ce6b0c..891cf67 100644
--- a/src/common/test_assembler.h
+++ b/src/common/test_assembler.h
@@ -60,12 +60,12 @@
 #include <vector>
 #include <string>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
 
 using std::list;
-using std::string;
 using std::vector;
 
 namespace test_assembler {
@@ -271,7 +271,10 @@
  public:
   Section(Endianness endianness = kUnsetEndian)
       : endianness_(endianness) { };
-  ~Section() { };
+
+  // A base class destructor should be either public and virtual,
+  // or protected and nonvirtual.
+  virtual ~Section() { };
 
   // Set the default endianness of this section to ENDIANNESS. This
   // sets the behavior of the D<N> appending functions. If the
diff --git a/src/common/test_assembler_unittest.cc b/src/common/test_assembler_unittest.cc
index 5db1326..d4e95ef 100644
--- a/src/common/test_assembler_unittest.cc
+++ b/src/common/test_assembler_unittest.cc
@@ -36,12 +36,12 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 
 using google_breakpad::test_assembler::Label;
 using google_breakpad::test_assembler::Section;
 using google_breakpad::test_assembler::kBigEndian;
 using google_breakpad::test_assembler::kLittleEndian;
-using std::string;
 using testing::Test;
 
 TEST(ConstructLabel, Simple) {
diff --git a/src/common/tests/auto_tempdir.h b/src/common/tests/auto_tempdir.h
index ccfd81b..9c84177 100644
--- a/src/common/tests/auto_tempdir.h
+++ b/src/common/tests/auto_tempdir.h
@@ -38,6 +38,7 @@
 #include <string>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 
 #if !defined(__ANDROID__)
 #define TEMPDIR "/tmp"
@@ -59,12 +60,12 @@
     DeleteRecursively(path_);
   }
 
-  const std::string& path() const {
+  const string& path() const {
     return path_;
   }
 
  private:
-  void DeleteRecursively(const std::string& path) {
+  void DeleteRecursively(const string& path) {
     // First remove any files in the dir
     DIR* dir = opendir(path.c_str());
     if (!dir)
@@ -74,7 +75,7 @@
     while ((entry = readdir(dir)) != NULL) {
       if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
         continue;
-      std::string entry_path = path + "/" + entry->d_name;
+      string entry_path = path + "/" + entry->d_name;
       struct stat stats;
       EXPECT_TRUE(lstat(entry_path.c_str(), &stats) == 0);
       if (S_ISDIR(stats.st_mode))
@@ -90,7 +91,7 @@
   AutoTempDir(const AutoTempDir&);
   AutoTempDir& operator=(const AutoTempDir&);
 
-  std::string path_;
+  string path_;
 };
 
 }  // namespace google_breakpad
diff --git a/src/common/using_std_string.h b/src/common/using_std_string.h
new file mode 100644
index 0000000..13c1da5
--- /dev/null
+++ b/src/common/using_std_string.h
@@ -0,0 +1,65 @@
+// -*- mode: C++ -*-
+
+// Copyright (c) 2012, 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.
+
+// Original author: Ivan Penkov
+
+// using_std_string.h: Allows building this code in environments where
+//                     global string (::string) exists.
+//
+// The problem:
+// -------------
+// Let's say you want to build this code in an environment where a global
+// string type is defined (i.e. ::string).  Now, let's suppose that ::string
+// is different that std::string and you'd like to have the option to easily
+// choose between the two string types.  Ideally you'd like to control which
+// string type is chosen by simply #defining an identifier.
+//
+// The solution:
+// -------------
+// #define HAS_GLOBAL_STRING somewhere in a global header file and then
+// globally replace std::string with string.  Then include this header
+// file everywhere where string is used.  If you want to revert back to
+// using std::string, simply remove the #define (HAS_GLOBAL_STRING).
+
+#ifndef THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
+#define THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
+
+#ifdef HAS_GLOBAL_STRING
+  typedef ::string google_breakpad_string;
+#else
+  using std::string;
+  typedef std::string google_breakpad_string;
+#endif
+
+// Inicates that type google_breakpad_string is defined
+#define HAS_GOOGLE_BREAKPAD_STRING
+
+#endif  // THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h
index a92007a..a43e229 100644
--- a/src/google_breakpad/common/minidump_format.h
+++ b/src/google_breakpad/common/minidump_format.h
@@ -611,7 +611,8 @@
   MD_OS_MAC_OS_X      = 0x8101,  /* Mac OS X/Darwin */
   MD_OS_IOS           = 0x8102,  /* iOS */
   MD_OS_LINUX         = 0x8201,  /* Linux */
-  MD_OS_SOLARIS       = 0x8202   /* Solaris */
+  MD_OS_SOLARIS       = 0x8202,  /* Solaris */
+  MD_OS_ANDROID       = 0x8203   /* Android */
 } MDOSPlatform;
 
 
diff --git a/src/google_breakpad/processor/basic_source_line_resolver.h b/src/google_breakpad/processor/basic_source_line_resolver.h
index f77b3bb..8bda578 100644
--- a/src/google_breakpad/processor/basic_source_line_resolver.h
+++ b/src/google_breakpad/processor/basic_source_line_resolver.h
@@ -39,12 +39,13 @@
 #define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
 
 #include <map>
+#include <string>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/source_line_resolver_base.h"
 
 namespace google_breakpad {
 
-using std::string;
 using std::map;
 
 class BasicSourceLineResolver : public SourceLineResolverBase {
diff --git a/src/google_breakpad/processor/code_module.h b/src/google_breakpad/processor/code_module.h
index 38ee956..24b88fb 100644
--- a/src/google_breakpad/processor/code_module.h
+++ b/src/google_breakpad/processor/code_module.h
@@ -36,12 +36,12 @@
 #define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
 
 #include <string>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
 
-using std::string;
-
 class CodeModule {
  public:
   virtual ~CodeModule() {}
diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
index 012a813..3dfbef2 100644
--- a/src/google_breakpad/processor/minidump.h
+++ b/src/google_breakpad/processor/minidump.h
@@ -88,6 +88,7 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/processor/code_module.h"
 #include "google_breakpad/processor/code_modules.h"
@@ -98,7 +99,6 @@
 
 
 using std::map;
-using std::string;
 using std::vector;
 
 
diff --git a/src/google_breakpad/processor/minidump_processor.h b/src/google_breakpad/processor/minidump_processor.h
index 3ed0ebf..216e972 100644
--- a/src/google_breakpad/processor/minidump_processor.h
+++ b/src/google_breakpad/processor/minidump_processor.h
@@ -32,12 +32,12 @@
 
 #include <assert.h>
 #include <string>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
 
-using std::string;
-
 class Minidump;
 class ProcessState;
 class SourceLineResolverInterface;
diff --git a/src/google_breakpad/processor/process_state.h b/src/google_breakpad/processor/process_state.h
index f3f2ec4..8d71457 100644
--- a/src/google_breakpad/processor/process_state.h
+++ b/src/google_breakpad/processor/process_state.h
@@ -36,13 +36,14 @@
 
 #include <string>
 #include <vector>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "google_breakpad/processor/system_info.h"
 #include "google_breakpad/processor/minidump.h"
 
 namespace google_breakpad {
 
-using std::string;
 using std::vector;
 
 class CallStack;
diff --git a/src/google_breakpad/processor/source_line_resolver_interface.h b/src/google_breakpad/processor/source_line_resolver_interface.h
index 9fe7ef4..4e9dd4b 100644
--- a/src/google_breakpad/processor/source_line_resolver_interface.h
+++ b/src/google_breakpad/processor/source_line_resolver_interface.h
@@ -35,13 +35,13 @@
 #define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__
 
 #include <string>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "google_breakpad/processor/code_module.h"
 
 namespace google_breakpad {
 
-using std::string;
-
 struct StackFrame;
 struct WindowsFrameInfo;
 class CFIFrameInfo;
diff --git a/src/google_breakpad/processor/stack_frame.h b/src/google_breakpad/processor/stack_frame.h
index c444993..2f31e5c 100644
--- a/src/google_breakpad/processor/stack_frame.h
+++ b/src/google_breakpad/processor/stack_frame.h
@@ -31,14 +31,14 @@
 #define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__
 
 #include <string>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
 
 class CodeModule;
 
-using std::string;
-
 struct StackFrame {
   // Indicates how well the instruction pointer derived during
   // stack walking is trusted. Since the stack walker can resort to
diff --git a/src/google_breakpad/processor/stackwalker.h b/src/google_breakpad/processor/stackwalker.h
index b184d02..6a0c3e7 100644
--- a/src/google_breakpad/processor/stackwalker.h
+++ b/src/google_breakpad/processor/stackwalker.h
@@ -43,6 +43,8 @@
 
 #include <set>
 #include <string>
+
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "google_breakpad/processor/code_modules.h"
 #include "google_breakpad/processor/memory_region.h"
@@ -189,7 +191,7 @@
   // A list of modules that we haven't found symbols for.  We track
   // this in order to avoid repeatedly looking them up again within
   // one minidump.
-  set<std::string> no_symbol_modules_;
+  set<string> no_symbol_modules_;
 
   // The maximum number of frames Stackwalker will walk through.
   // This defaults to 1024 to prevent infinite loops.
diff --git a/src/google_breakpad/processor/symbol_supplier.h b/src/google_breakpad/processor/symbol_supplier.h
index 8c4d7f7..dccab50 100644
--- a/src/google_breakpad/processor/symbol_supplier.h
+++ b/src/google_breakpad/processor/symbol_supplier.h
@@ -34,10 +34,10 @@
 #define GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__
 
 #include <string>
+#include "common/using_std_string.h"
 
 namespace google_breakpad {
 
-using std::string;
 class CodeModule;
 struct SystemInfo;
 
diff --git a/src/google_breakpad/processor/system_info.h b/src/google_breakpad/processor/system_info.h
index fdbdbfd..4a25048 100644
--- a/src/google_breakpad/processor/system_info.h
+++ b/src/google_breakpad/processor/system_info.h
@@ -37,9 +37,9 @@
 
 #include <string>
 
-namespace google_breakpad {
+#include "common/using_std_string.h"
 
-using std::string;
+namespace google_breakpad {
 
 struct SystemInfo {
  public:
diff --git a/src/processor/basic_code_module.h b/src/processor/basic_code_module.h
index e3955d2..635c09a 100644
--- a/src/processor/basic_code_module.h
+++ b/src/processor/basic_code_module.h
@@ -43,12 +43,11 @@
 
 #include <string>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/code_module.h"
 
 namespace google_breakpad {
 
-using std::string;
-
 class BasicCodeModule : public CodeModule {
  public:
   // Creates a new BasicCodeModule given any existing CodeModule
diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
index c241ea0..2a483e3 100644
--- a/src/processor/basic_source_line_resolver_unittest.cc
+++ b/src/processor/basic_source_line_resolver_unittest.cc
@@ -32,6 +32,7 @@
 #include <string>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/code_module.h"
 #include "google_breakpad/processor/stack_frame.h"
@@ -44,7 +45,6 @@
 
 namespace {
 
-using std::string;
 using google_breakpad::BasicSourceLineResolver;
 using google_breakpad::CFIFrameInfo;
 using google_breakpad::CodeModule;
@@ -200,6 +200,7 @@
   ASSERT_EQ(frame.source_line_base, 0x1000);
   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
   ASSERT_TRUE(windows_frame_info.get());
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
   ASSERT_EQ(windows_frame_info->program_string,
             "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =");
@@ -219,6 +220,7 @@
   ASSERT_EQ(frame.source_line, 0);
   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
   ASSERT_TRUE(windows_frame_info.get());
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN);
   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
   ASSERT_TRUE(windows_frame_info->program_string.empty());
 
@@ -228,6 +230,7 @@
   ASSERT_TRUE(frame.source_file_name.empty());
   ASSERT_EQ(frame.source_line, 0);
   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
   ASSERT_TRUE(windows_frame_info.get());
   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
   ASSERT_FALSE(windows_frame_info->program_string.empty());
@@ -351,6 +354,7 @@
   ASSERT_EQ(frame.source_line_base, 0x2180);
   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
   ASSERT_TRUE(windows_frame_info.get());
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
   ASSERT_EQ(windows_frame_info->prolog_size, 1);
 
   frame.instruction = 0x216f;
diff --git a/src/processor/binarystream.cc b/src/processor/binarystream.cc
index c8ee218..9ed3b70 100644
--- a/src/processor/binarystream.cc
+++ b/src/processor/binarystream.cc
@@ -30,15 +30,16 @@
 #include <arpa/inet.h>
 #include <limits.h>
 
+#include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "processor/binarystream.h"
 
 namespace google_breakpad {
-using std::string;
 using std::vector;
 
-binarystream &binarystream::operator>>(std::string &str) {
+binarystream &binarystream::operator>>(string &str) {
   u_int16_t length;
   *this >> length;
   if (eof())
@@ -83,7 +84,7 @@
   return *this;
 }
 
-binarystream &binarystream::operator<<(const std::string &str) {
+binarystream &binarystream::operator<<(const string &str) {
   if (str.length() > USHRT_MAX) {
     // truncate to 16-bit length
     *this << static_cast<u_int16_t>(USHRT_MAX);
diff --git a/src/processor/binarystream.h b/src/processor/binarystream.h
index 8769c25..0465715 100644
--- a/src/processor/binarystream.h
+++ b/src/processor/binarystream.h
@@ -28,8 +28,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // binarystream implements part of the std::iostream interface as a
-// wrapper around std::stringstream to allow reading and writing
-// std::string and integers of known size.
+// wrapper around std::stringstream to allow reading and writing strings
+// and integers of known size.
 
 #ifndef GOOGLE_BREAKPAD_PROCESSOR_BINARYSTREAM_H_
 #define GOOGLE_BREAKPAD_PROCESSOR_BINARYSTREAM_H_
@@ -37,6 +37,7 @@
 #include <sstream>
 #include <string>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
@@ -47,21 +48,21 @@
  public:
   explicit binarystream(ios_base::openmode which = ios_base::out|ios_base::in)
     : stream_(which) {}
-  explicit binarystream(const std::string &str,
+  explicit binarystream(const string &str,
                         ios_base::openmode which = ios_base::out|ios_base::in)
     : stream_(str, which) {}
   explicit binarystream(const char *str, size_t size,
                         ios_base::openmode which = ios_base::out|ios_base::in)
-    : stream_(std::string(str, size), which) {}
+    : stream_(string(str, size), which) {}
 
-  binarystream &operator>>(std::string &str);
+  binarystream &operator>>(string &str);
   binarystream &operator>>(u_int8_t &u8);
   binarystream &operator>>(u_int16_t &u16);
   binarystream &operator>>(u_int32_t &u32);
   binarystream &operator>>(u_int64_t &u64);
 
   // Note: strings are truncated at 65535 characters
-  binarystream &operator<<(const std::string &str);
+  binarystream &operator<<(const string &str);
   binarystream &operator<<(u_int8_t u8);
   binarystream &operator<<(u_int16_t u16);
   binarystream &operator<<(u_int32_t u32);
@@ -70,8 +71,8 @@
   // Forward a few methods directly from the stream object
   bool eof() const { return stream_.eof(); }
   void clear() { stream_.clear(); }
-  std::string str() const { return stream_.str(); }
-  void str(const std::string &s) { stream_.str(s); }
+  string str() const { return stream_.str(); }
+  void str(const string &s) { stream_.str(s); }
     
   // Seek both read and write pointers to the beginning of the stream.
   void rewind() {
diff --git a/src/processor/binarystream_unittest.cc b/src/processor/binarystream_unittest.cc
index 2ed76e2..2812319 100644
--- a/src/processor/binarystream_unittest.cc
+++ b/src/processor/binarystream_unittest.cc
@@ -32,11 +32,11 @@
 #include <vector>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "processor/binarystream.h"
 
 namespace {
 using std::ios_base;
-using std::string;
 using std::vector;
 using google_breakpad::binarystream;
 
diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
index fe06fb4..4bbbd1e 100644
--- a/src/processor/cfi_frame_info.h
+++ b/src/processor/cfi_frame_info.h
@@ -41,12 +41,12 @@
 #include <map>
 #include <string>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 namespace google_breakpad {
 
 using std::map;
-using std::string;
 
 class MemoryRegion;
 
diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
index 979d4a3..cd48e16 100644
--- a/src/processor/cfi_frame_info_unittest.cc
+++ b/src/processor/cfi_frame_info_unittest.cc
@@ -35,6 +35,7 @@
 #include <string.h>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "processor/cfi_frame_info.h"
 #include "google_breakpad/processor/memory_region.h"
 
@@ -43,7 +44,6 @@
 using google_breakpad::CFIRuleParser;
 using google_breakpad::MemoryRegion;
 using google_breakpad::SimpleCFIWalker;
-using std::string;
 using testing::_;
 using testing::A;
 using testing::AtMost;
diff --git a/src/processor/exploitability.cc b/src/processor/exploitability.cc
index eb0b4d3..459e7ce 100644
--- a/src/processor/exploitability.cc
+++ b/src/processor/exploitability.cc
@@ -79,6 +79,7 @@
     case MD_OS_LINUX:
     case MD_OS_UNIX:
     case MD_OS_SOLARIS:
+    case MD_OS_ANDROID:
     default: {
       platform_exploitability = NULL;
       break;
diff --git a/src/processor/exploitability_unittest.cc b/src/processor/exploitability_unittest.cc
index 4de6f1d..ce7a6f7 100644
--- a/src/processor/exploitability_unittest.cc
+++ b/src/processor/exploitability_unittest.cc
@@ -43,6 +43,7 @@
 #include <string>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/call_stack.h"
 #include "google_breakpad/processor/code_module.h"
@@ -78,7 +79,6 @@
 using google_breakpad::ProcessState;
 using google_breakpad::SymbolSupplier;
 using google_breakpad::SystemInfo;
-using std::string;
 
 class TestSymbolSupplier : public SymbolSupplier {
  public:
diff --git a/src/processor/fast_source_line_resolver.cc b/src/processor/fast_source_line_resolver.cc
index 45c1f0f..a7b9933 100644
--- a/src/processor/fast_source_line_resolver.cc
+++ b/src/processor/fast_source_line_resolver.cc
@@ -41,8 +41,10 @@
 #include "processor/fast_source_line_resolver_types.h"
 
 #include <map>
+#include <string>
 #include <utility>
 
+#include "common/using_std_string.h"
 #include "processor/module_factory.h"
 #include "processor/scoped_ptr.h"
 
@@ -107,10 +109,15 @@
 // WFI: WindowsFrameInfo.
 // Returns a WFI object reading from a raw memory chunk of data
 WindowsFrameInfo FastSourceLineResolver::CopyWFI(const char *raw) {
-  // The first 4Bytes of int data are unused.
-  // They corresponds to "int valid;" data member of WFI.
+  const WindowsFrameInfo::StackInfoTypes type =
+     static_cast<const WindowsFrameInfo::StackInfoTypes>(
+         *reinterpret_cast<const int32_t*>(raw));
+
+  // The first 8 bytes of int data are unused.
+  // They correspond to "StackInfoTypes type_;" and "int valid;"
+  // data member of WFI.
   const u_int32_t *para_uint32 = reinterpret_cast<const u_int32_t*>(
-      raw + sizeof(int32_t));
+      raw + 2 * sizeof(int32_t));
 
   u_int32_t prolog_size = para_uint32[0];;
   u_int32_t epilog_size = para_uint32[1];
@@ -120,9 +127,10 @@
   u_int32_t max_stack_size = para_uint32[5];
   const char *boolean = reinterpret_cast<const char*>(para_uint32 + 6);
   bool allocates_base_pointer = (*boolean != 0);
-  std::string program_string = boolean + 1;
+  string program_string = boolean + 1;
 
-  return WindowsFrameInfo(prolog_size,
+  return WindowsFrameInfo(type,
+                          prolog_size,
                           epilog_size,
                           parameter_size,
                           saved_register_size,
diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
index a4a9209..d0323ce 100644
--- a/src/processor/fast_source_line_resolver_unittest.cc
+++ b/src/processor/fast_source_line_resolver_unittest.cc
@@ -43,6 +43,7 @@
 #include <string>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/code_module.h"
 #include "google_breakpad/processor/stack_frame.h"
 #include "google_breakpad/processor/memory_region.h"
@@ -52,7 +53,6 @@
 
 namespace {
 
-using std::string;
 using google_breakpad::SourceLineResolverBase;
 using google_breakpad::BasicSourceLineResolver;
 using google_breakpad::FastSourceLineResolver;
@@ -248,6 +248,7 @@
   ASSERT_EQ(frame.source_line, 0);
   windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
   ASSERT_TRUE(windows_frame_info.get());
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN);
   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
   ASSERT_TRUE(windows_frame_info->program_string.empty());
 
@@ -258,6 +259,7 @@
   ASSERT_EQ(frame.source_line, 0);
   windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
   ASSERT_TRUE(windows_frame_info.get());
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
   ASSERT_FALSE(windows_frame_info->program_string.empty());
 
@@ -380,6 +382,7 @@
   ASSERT_EQ(frame.source_line_base, 0x2180);
   windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
   ASSERT_TRUE(windows_frame_info.get());
+  ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
   ASSERT_EQ(windows_frame_info->prolog_size, 1);
 
   frame.instruction = 0x216f;
diff --git a/src/processor/logging.cc b/src/processor/logging.cc
index 70f6958..a6e15ca 100644
--- a/src/processor/logging.cc
+++ b/src/processor/logging.cc
@@ -39,6 +39,9 @@
 #include <string.h>
 #include <time.h>
 
+#include <string>
+
+#include "common/using_std_string.h"
 #include "processor/logging.h"
 #include "processor/pathname_stripper.h"
 
@@ -80,25 +83,25 @@
   stream_ << std::endl;
 }
 
-std::string HexString(u_int32_t number) {
+string HexString(u_int32_t number) {
   char buffer[11];
   snprintf(buffer, sizeof(buffer), "0x%x", number);
-  return std::string(buffer);
+  return string(buffer);
 }
 
-std::string HexString(u_int64_t number) {
+string HexString(u_int64_t number) {
   char buffer[19];
   snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number);
-  return std::string(buffer);
+  return string(buffer);
 }
 
-std::string HexString(int number) {
+string HexString(int number) {
   char buffer[19];
   snprintf(buffer, sizeof(buffer), "0x%x", number);
-  return std::string(buffer);
+  return string(buffer);
 }
 
-int ErrnoString(std::string *error_string) {
+int ErrnoString(string *error_string) {
   assert(error_string);
 
   // strerror isn't necessarily thread-safe.  strerror_r would be preferrable,
diff --git a/src/processor/logging.h b/src/processor/logging.h
index 642506d..6a964f6 100644
--- a/src/processor/logging.h
+++ b/src/processor/logging.h
@@ -60,6 +60,7 @@
 #include <iostream>
 #include <string>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 
 #ifdef BP_LOGGING_INCLUDE
@@ -118,14 +119,14 @@
 };
 
 // Returns number formatted as a hexadecimal string, such as "0x7b".
-std::string HexString(u_int32_t number);
-std::string HexString(u_int64_t number);
-std::string HexString(int number);
+string HexString(u_int32_t number);
+string HexString(u_int64_t number);
+string HexString(int number);
 
 // Returns the error code as set in the global errno variable, and sets
 // error_string, a required argument, to a string describing that error
 // code.
-int ErrnoString(std::string *error_string);
+int ErrnoString(string *error_string);
 
 }  // namespace google_breakpad
 
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
index 3ca52ff..d88101f 100644
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -1760,6 +1760,7 @@
     case MD_OS_MAC_OS_X:
     case MD_OS_IOS:
     case MD_OS_SOLARIS:
+    case MD_OS_ANDROID:
     case MD_OS_LINUX: {
       // TODO(mmentovai): support uuid extension if present, otherwise fall
       // back to version (from LC_ID_DYLIB?), otherwise fall back to something
@@ -3079,13 +3080,13 @@
 
 
 string MinidumpSystemInfo::GetOS() {
+  string os;
+
   if (!valid_) {
     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
-    return NULL;
+    return os;
   }
 
-  string os;
-
   switch (system_info_.platform_id) {
     case MD_OS_WIN32_NT:
     case MD_OS_WIN32_WINDOWS:
@@ -3108,6 +3109,10 @@
       os = "solaris";
       break;
 
+    case MD_OS_ANDROID:
+      os = "android";
+      break;
+
     default:
       BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
                       HexString(system_info_.platform_id);
diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
index 40b2873..6dbe81e 100644
--- a/src/processor/minidump_processor.cc
+++ b/src/processor/minidump_processor.cc
@@ -401,6 +401,11 @@
       break;
     }
 
+    case MD_OS_ANDROID: {
+      info->os = "Android";
+      break;
+    }
+
     default: {
       // Assign the numeric platform ID into the OS string.
       char os_string[11];
@@ -838,6 +843,7 @@
       break;
     }
 
+    case MD_OS_ANDROID:
     case MD_OS_LINUX: {
       switch (exception_code) {
         case MD_EXCEPTION_CODE_LIN_SIGHUP:
diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc
index fcac48f..a8e1208 100644
--- a/src/processor/minidump_processor_unittest.cc
+++ b/src/processor/minidump_processor_unittest.cc
@@ -39,6 +39,7 @@
 #include <utility>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/call_stack.h"
 #include "google_breakpad/processor/code_module.h"
@@ -79,7 +80,6 @@
 using google_breakpad::scoped_ptr;
 using google_breakpad::SymbolSupplier;
 using google_breakpad::SystemInfo;
-using std::string;
 using ::testing::_;
 using ::testing::Mock;
 using ::testing::Ne;
@@ -165,8 +165,8 @@
                                                  symbol_file);
   if (s == FOUND) {
     std::ifstream in(symbol_file->c_str());
-    std::getline(in, *symbol_data, std::string::traits_type::to_char_type(
-                     std::string::traits_type::eof()));
+    std::getline(in, *symbol_data, string::traits_type::to_char_type(
+                     string::traits_type::eof()));
     in.close();
   }
 
diff --git a/src/processor/minidump_stackwalk.cc b/src/processor/minidump_stackwalk.cc
index 86f679e..b37148f 100644
--- a/src/processor/minidump_stackwalk.cc
+++ b/src/processor/minidump_stackwalk.cc
@@ -39,6 +39,7 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/call_stack.h"
 #include "google_breakpad/processor/code_module.h"
@@ -54,7 +55,6 @@
 
 namespace {
 
-using std::string;
 using std::vector;
 using google_breakpad::BasicSourceLineResolver;
 using google_breakpad::CallStack;
@@ -575,7 +575,7 @@
   }
 
   // extra arguments are symbol paths
-  std::vector<std::string> symbol_paths;
+  std::vector<string> symbol_paths;
   if (argc > symbol_path_arg) {
     for (int argi = symbol_path_arg; argi < argc; ++argi)
       symbol_paths.push_back(argv[argi]);
diff --git a/src/processor/minidump_unittest.cc b/src/processor/minidump_unittest.cc
index d1c91a8..ce14230 100644
--- a/src/processor/minidump_unittest.cc
+++ b/src/processor/minidump_unittest.cc
@@ -36,7 +36,9 @@
 #include <stdlib.h>
 #include <string>
 #include <vector>
+
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/processor/minidump.h"
 #include "processor/logging.h"
@@ -69,7 +71,6 @@
 using google_breakpad::test_assembler::kLittleEndian;
 using std::ifstream;
 using std::istringstream;
-using std::string;
 using std::vector;
 using ::testing::Return;
 
diff --git a/src/processor/module_comparer.cc b/src/processor/module_comparer.cc
index 837d854..09b85e0 100644
--- a/src/processor/module_comparer.cc
+++ b/src/processor/module_comparer.cc
@@ -240,6 +240,7 @@
 
 bool ModuleComparer::CompareWFI(const WindowsFrameInfo& wfi1,
                                const WindowsFrameInfo& wfi2) const {
+  ASSERT_TRUE(wfi1.type_ == wfi2.type_);
   ASSERT_TRUE(wfi1.valid == wfi2.valid);
   ASSERT_TRUE(wfi1.prolog_size == wfi2.prolog_size);
   ASSERT_TRUE(wfi1.epilog_size == wfi2.epilog_size);
diff --git a/src/processor/pathname_stripper.h b/src/processor/pathname_stripper.h
index 17db75d..423ca0d 100644
--- a/src/processor/pathname_stripper.h
+++ b/src/processor/pathname_stripper.h
@@ -36,9 +36,9 @@
 
 #include <string>
 
-namespace google_breakpad {
+#include "common/using_std_string.h"
 
-using std::string;
+namespace google_breakpad {
 
 class PathnameStripper {
  public:
diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
index eb53b1e..94b6619 100644
--- a/src/processor/postfix_evaluator.h
+++ b/src/processor/postfix_evaluator.h
@@ -74,10 +74,11 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
 using std::map;
-using std::string;
 using std::vector;
 
 class MemoryRegion;
diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
index f6cbcf0..00c8fd8 100644
--- a/src/processor/postfix_evaluator_unittest.cc
+++ b/src/processor/postfix_evaluator_unittest.cc
@@ -38,6 +38,7 @@
 
 #include "processor/postfix_evaluator-inl.h"
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "google_breakpad/processor/memory_region.h"
 #include "processor/logging.h"
@@ -47,7 +48,6 @@
 
 
 using std::map;
-using std::string;
 using google_breakpad::MemoryRegion;
 using google_breakpad::PostfixEvaluator;
 
diff --git a/src/processor/simple_serializer-inl.h b/src/processor/simple_serializer-inl.h
index a6f5496..1faf5ef 100644
--- a/src/processor/simple_serializer-inl.h
+++ b/src/processor/simple_serializer-inl.h
@@ -132,6 +132,7 @@
  public:
   static size_t SizeOf(const WindowsFrameInfo &wfi) {
     unsigned int size = 0;
+    size += sizeof(int32_t);  // wfi.type_
     size += SimpleSerializer<int32_t>::SizeOf(wfi.valid);
     size += SimpleSerializer<u_int32_t>::SizeOf(wfi.prolog_size);
     size += SimpleSerializer<u_int32_t>::SizeOf(wfi.epilog_size);
@@ -144,6 +145,8 @@
     return size;
   }
   static char *Write(const WindowsFrameInfo &wfi, char *dest) {
+    dest = SimpleSerializer<int32_t>::Write(
+        static_cast<const int32_t>(wfi.type_), dest);
     dest = SimpleSerializer<int32_t>::Write(wfi.valid, dest);
     dest = SimpleSerializer<u_int32_t>::Write(wfi.prolog_size, dest);
     dest = SimpleSerializer<u_int32_t>::Write(wfi.epilog_size, dest);
diff --git a/src/processor/simple_symbol_supplier.cc b/src/processor/simple_symbol_supplier.cc
index 76820e1..4a3a105 100644
--- a/src/processor/simple_symbol_supplier.cc
+++ b/src/processor/simple_symbol_supplier.cc
@@ -44,6 +44,7 @@
 #include <iostream>
 #include <fstream>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/code_module.h"
 #include "google_breakpad/processor/system_info.h"
 #include "processor/logging.h"
@@ -87,8 +88,8 @@
 
   if (s == FOUND) {
     std::ifstream in(symbol_file->c_str());
-    std::getline(in, *symbol_data, std::string::traits_type::to_char_type(
-                     std::string::traits_type::eof()));
+    std::getline(in, *symbol_data, string::traits_type::to_char_type(
+                     string::traits_type::eof()));
     in.close();
   }
   return s;
diff --git a/src/processor/simple_symbol_supplier.h b/src/processor/simple_symbol_supplier.h
index e1c1619..e19b194 100644
--- a/src/processor/simple_symbol_supplier.h
+++ b/src/processor/simple_symbol_supplier.h
@@ -80,12 +80,12 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/processor/symbol_supplier.h"
 
 namespace google_breakpad {
 
 using std::map;
-using std::string;
 using std::vector;
 
 class CodeModule;
diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc
index fd9ccdf..5a9ddb1 100644
--- a/src/processor/stackwalker_amd64.cc
+++ b/src/processor/stackwalker_amd64.cc
@@ -146,18 +146,13 @@
     const vector<StackFrame *> &frames) {
   StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64 *>(frames.back());
   u_int64_t last_rsp = last_frame->context.rsp;
-  u_int64_t caller_rsp, caller_rip;
-  
-  if (!ScanForReturnAddress(last_rsp, &caller_rsp, &caller_rip)) {
+  u_int64_t caller_rip_address, caller_rip;
+
+  if (!ScanForReturnAddress(last_rsp, &caller_rip_address, &caller_rip)) {
     // No plausible return address was found.
     return NULL;
   }
 
-  // ScanForReturnAddress found a reasonable return address. Advance
-  // %rsp to the location above the one where the return address was
-  // found.
-  caller_rsp += 8;
-
   // Create a new stack frame (ownership will be transferred to the caller)
   // and fill it in.
   StackFrameAMD64 *frame = new StackFrameAMD64();
@@ -165,10 +160,34 @@
   frame->trust = StackFrame::FRAME_TRUST_SCAN;
   frame->context = last_frame->context;
   frame->context.rip = caller_rip;
-  frame->context.rsp = caller_rsp;
+  // The caller's %rsp is directly underneath the return address pushed by
+  // the call.
+  frame->context.rsp = caller_rip_address + 8;
   frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP |
                             StackFrameAMD64::CONTEXT_VALID_RSP;
 
+  // Other unwinders give up if they don't have an %rbp value, so see if we
+  // can pass some plausible value on.
+  if (last_frame->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP) {
+    // Functions typically push their caller's %rbp immediately upon entry,
+    // and then set %rbp to point to that. So if the callee's %rbp is
+    // pointing to the first word below the alleged return address, presume
+    // that the caller's %rbp is saved there.
+    if (caller_rip_address - 8 == last_frame->context.rbp) {
+      u_int64_t caller_rbp = 0;
+      if (memory_->GetMemoryAtAddress(last_frame->context.rbp, &caller_rbp) &&
+          caller_rbp > caller_rip_address) {
+        frame->context.rbp = caller_rbp;
+        frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP;
+      }
+    } else if (last_frame->context.rbp >= caller_rip_address + 8) {
+      // If the callee's %rbp is plausible as a value for the caller's
+      // %rbp, presume that the callee left it unchanged.
+      frame->context.rbp = last_frame->context.rbp;
+      frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP;
+    }
+  }
+
   return frame;
 }
 
diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc
index 0cb5fd5..f3723c0 100644
--- a/src/processor/stackwalker_amd64_unittest.cc
+++ b/src/processor/stackwalker_amd64_unittest.cc
@@ -37,6 +37,7 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/call_stack.h"
@@ -54,7 +55,6 @@
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Label;
 using google_breakpad::test_assembler::Section;
-using std::string;
 using std::vector;
 using testing::_;
 using testing::Return;
@@ -92,9 +92,7 @@
   // Set the Breakpad symbol information that supplier should return for
   // MODULE to INFO.
   void SetModuleSymbols(MockCodeModule *module, const string &info) {
-    unsigned int buffer_size = info.size() + 1;
-    char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
-    strcpy(buffer, info.c_str());
+    char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info);
     EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
       .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
                             Return(MockSymbolSupplier::FOUND)));
@@ -182,7 +180,7 @@
   stack_section.start() = 0x8000000080000000ULL;
   u_int64_t return_address1 = 0x50000000b0000100ULL;
   u_int64_t return_address2 = 0x50000000b0000900ULL;
-  Label frame1_sp, frame2_sp;
+  Label frame1_sp, frame2_sp, frame1_rbp;
   stack_section
     // frame 0
     .Append(16, 0)                      // space
@@ -198,6 +196,11 @@
     .D64(0x40000000b0000000ULL)         // more junk
     .D64(0x50000000d0000000ULL)
 
+    .Mark(&frame1_rbp)
+    .D64(stack_section.start())         // This is in the right place to be
+                                        // a saved rbp, but it's bogus, so
+                                        // we shouldn't report it.
+
     .D64(return_address2)               // actual return address
     // frame 2
     .Mark(&frame2_sp)
@@ -206,6 +209,7 @@
   RegionFromSection();
     
   raw_context.rip = 0x40000000c0000200ULL;
+  raw_context.rbp = frame1_rbp.Value();
   raw_context.rsp = stack_section.start().Value();
 
   StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
@@ -222,10 +226,12 @@
   StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
-             StackFrameAMD64::CONTEXT_VALID_RSP),
+             StackFrameAMD64::CONTEXT_VALID_RSP |
+             StackFrameAMD64::CONTEXT_VALID_RBP),
             frame1->context_validity);
   EXPECT_EQ(return_address1, frame1->context.rip);
   EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+  EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
 
   StackFrameAMD64 *frame2 = static_cast<StackFrameAMD64 *>(frames->at(2));
   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
@@ -243,7 +249,7 @@
   // lies within a function's bounds.
   stack_section.start() = 0x8000000080000000ULL;
   u_int64_t return_address = 0x50000000b0000110ULL;
-  Label frame1_sp;
+  Label frame1_sp, frame1_rbp;
 
   stack_section
     // frame 0
@@ -258,10 +264,12 @@
     .D64(return_address)                // actual return address
     // frame 1
     .Mark(&frame1_sp)
-    .Append(32, 0);                     // end of stack
+    .Append(32, 0)                      // end of stack
+    .Mark(&frame1_rbp);
   RegionFromSection();
     
   raw_context.rip = 0x40000000c0000200ULL;
+  raw_context.rbp = frame1_rbp.Value();
   raw_context.rsp = stack_section.start().Value();
 
   SetModuleSymbols(&module1,
@@ -286,14 +294,81 @@
   StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
   ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
-             StackFrameAMD64::CONTEXT_VALID_RSP),
+             StackFrameAMD64::CONTEXT_VALID_RSP |
+             StackFrameAMD64::CONTEXT_VALID_RBP),
             frame1->context_validity);
   EXPECT_EQ(return_address, frame1->context.rip);
   EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+  EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
   EXPECT_EQ("echidna", frame1->function_name);
   EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
 }
 
+TEST_F(GetCallerFrame, CallerPushedRBP) {
+  // Functions typically push their %rbp upon entry and set %rbp pointing
+  // there.  If stackwalking finds a plausible address for the next frame's
+  // %rbp directly below the return address, assume that it is indeed the
+  // next frame's %rbp.
+  stack_section.start() = 0x8000000080000000ULL;
+  u_int64_t return_address = 0x50000000b0000110ULL;
+  Label frame0_rbp, frame1_sp, frame1_rbp;
+
+  stack_section
+    // frame 0
+    .Append(16, 0)                      // space
+
+    .D64(0x40000000b0000000ULL)         // junk that's not
+    .D64(0x50000000b0000000ULL)         // a return address
+
+    .D64(0x40000000c0001000ULL)         // a couple of plausible addresses
+    .D64(0x50000000b000aaaaULL)         // that are not within functions
+
+    .Mark(&frame0_rbp)
+    .D64(frame1_rbp)                    // caller-pushed %rbp
+    .D64(return_address)                // actual return address
+    // frame 1
+    .Mark(&frame1_sp)
+    .Append(32, 0)                      // body of frame1
+    .Mark(&frame1_rbp);                 // end of stack
+  RegionFromSection();
+
+  raw_context.rip = 0x40000000c0000200ULL;
+  raw_context.rbp = frame0_rbp.Value();
+  raw_context.rsp = stack_section.start().Value();
+
+  SetModuleSymbols(&module1,
+                   // The youngest frame's function.
+                   "FUNC 100 400 10 sasquatch\n");
+  SetModuleSymbols(&module2,
+                   // The calling frame's function.
+                   "FUNC 100 400 10 yeti\n");
+
+  StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+                          &supplier, &resolver);
+  ASSERT_TRUE(walker.Walk(&call_stack));
+  frames = call_stack.frames();
+  ASSERT_EQ(2U, frames->size());
+
+  StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+  ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+  EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp);
+  EXPECT_EQ("sasquatch", frame0->function_name);
+  EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
+
+  StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+  ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+             StackFrameAMD64::CONTEXT_VALID_RSP |
+             StackFrameAMD64::CONTEXT_VALID_RBP),
+            frame1->context_validity);
+  EXPECT_EQ(return_address, frame1->context.rip);
+  EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+  EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
+  EXPECT_EQ("yeti", frame1->function_name);
+  EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
+}
+
 struct CFIFixture: public StackwalkerAMD64Fixture {
   CFIFixture() {
     // Provide a bunch of STACK CFI records; we'll walk to the caller
diff --git a/src/processor/stackwalker_arm_unittest.cc b/src/processor/stackwalker_arm_unittest.cc
index 6a623c2..10772ba 100644
--- a/src/processor/stackwalker_arm_unittest.cc
+++ b/src/processor/stackwalker_arm_unittest.cc
@@ -37,6 +37,7 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/call_stack.h"
@@ -56,7 +57,6 @@
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Label;
 using google_breakpad::test_assembler::Section;
-using std::string;
 using std::vector;
 using testing::_;
 using testing::Return;
@@ -94,9 +94,7 @@
   // Set the Breakpad symbol information that supplier should return for
   // MODULE to INFO.
   void SetModuleSymbols(MockCodeModule *module, const string &info) {
-    unsigned int buffer_size = info.size() + 1;
-    char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
-    strcpy(buffer, info.c_str());
+    char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info);
     EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
       .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
                             Return(MockSymbolSupplier::FOUND)));
diff --git a/src/processor/stackwalker_unittest_utils.h b/src/processor/stackwalker_unittest_utils.h
index d2e29f7..5257f81 100644
--- a/src/processor/stackwalker_unittest_utils.h
+++ b/src/processor/stackwalker_unittest_utils.h
@@ -40,6 +40,7 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "google_breakpad/processor/code_module.h"
 #include "google_breakpad/processor/code_modules.h"
@@ -54,7 +55,7 @@
   // Set this region's address and contents. If we have placed an
   // instance of this class in a test fixture class, individual tests
   // can use this to provide the region's contents.
-  void Init(u_int64_t base_address, const std::string &contents) {
+  void Init(u_int64_t base_address, const string &contents) {
     base_address_ = base_address;
     contents_ = contents;
   }
@@ -93,22 +94,22 @@
   }
 
   u_int64_t base_address_;
-  std::string contents_;
+  string contents_;
 };
 
 class MockCodeModule: public google_breakpad::CodeModule {
  public:
   MockCodeModule(u_int64_t base_address, u_int64_t size,
-                 const std::string &code_file, const std::string &version)
+                 const string &code_file, const string &version)
       : base_address_(base_address), size_(size), code_file_(code_file) { }
 
   u_int64_t base_address()       const { return base_address_; }
   u_int64_t size()               const { return size_; }
-  std::string code_file()        const { return code_file_; }
-  std::string code_identifier()  const { return code_file_; }
-  std::string debug_file()       const { return code_file_; }
-  std::string debug_identifier() const { return code_file_; }
-  std::string version()          const { return version_; }
+  string code_file()        const { return code_file_; }
+  string code_identifier()  const { return code_file_; }
+  string debug_file()       const { return code_file_; }
+  string debug_identifier() const { return code_file_; }
+  string version()          const { return version_; }
   const google_breakpad::CodeModule *Copy() const {
     abort(); // Tests won't use this.
   }
@@ -116,8 +117,8 @@
  private:
   u_int64_t base_address_;
   u_int64_t size_;
-  std::string code_file_;
-  std::string version_;
+  string code_file_;
+  string version_;
 };
 
 class MockCodeModules: public google_breakpad::CodeModules {
@@ -165,16 +166,39 @@
   typedef google_breakpad::SystemInfo SystemInfo;
   MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule *module,
                                            const SystemInfo *system_info,
-                                           std::string *symbol_file));
+                                           string *symbol_file));
   MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule *module,
                                            const SystemInfo *system_info,
-                                           std::string *symbol_file,
-                                           std::string *symbol_data));
+                                           string *symbol_file,
+                                           string *symbol_data));
   MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module,
                                                   const SystemInfo *system_info,
-                                                  std::string *symbol_file,
+                                                  string *symbol_file,
                                                   char **symbol_data));
   MOCK_METHOD1(FreeSymbolData, void(const CodeModule *module));
+
+  // Copies the passed string contents into a newly allocated buffer.
+  // The newly allocated buffer will be freed during destruction.
+  char* CopySymbolDataAndOwnTheCopy(const std::string &info) {
+    unsigned int buffer_size = info.size() + 1;
+    char *symbol_data = new char [buffer_size];
+    strcpy(symbol_data, info.c_str());
+    symbol_data_to_free_.push_back(symbol_data);
+    return symbol_data;
+  }
+
+  virtual ~MockSymbolSupplier() {
+    for (SymbolDataVector::const_iterator i = symbol_data_to_free_.begin();
+         i != symbol_data_to_free_.end(); i++) {
+      char* symbol_data = *i;
+      delete [] symbol_data;
+    }
+  }
+
+ private:
+  // List of symbol data to be freed upon destruction
+  typedef std::vector<char*> SymbolDataVector;
+  SymbolDataVector symbol_data_to_free_;
 };
 
 #endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
index 3c35b08..ba3b839 100644
--- a/src/processor/stackwalker_x86.cc
+++ b/src/processor/stackwalker_x86.cc
@@ -208,11 +208,27 @@
                             last_frame_callee_parameter_size +
                             last_frame_info->local_size +
                             last_frame_info->saved_register_size;
-  u_int32_t found; // dummy value
+
+  u_int32_t raSearchStartOld = raSearchStart;
+  u_int32_t found = 0; // dummy value
   // Scan up to three words above the calculated search value, in case
   // the stack was aligned to a quadword boundary.
-  ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
-  
+  if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) &&
+      last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT &&
+      last_frame->windows_frame_info != NULL &&
+      last_frame_info->type_ == WindowsFrameInfo::STACK_INFO_FPO &&
+      raSearchStartOld == raSearchStart &&
+      found == last_frame->context.eip) {
+    // The context frame represents an FPO-optimized Windows system call.
+    // On the top of the stack we have a pointer to the current instruction.
+    // This means that the callee has returned but the return address is still
+    // on the top of the stack which is very atypical situaltion.
+    // Skip one slot from the stack and do another scan in order to get the
+    // actual return address.
+    raSearchStart += 4;
+    ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
+  }
+
   // The difference between raSearch and raSearchStart is unknown,
   // but making them the same seems to work well in practice.
   dictionary[".raSearchStart"] = raSearchStart;
diff --git a/src/processor/stackwalker_x86_unittest.cc b/src/processor/stackwalker_x86_unittest.cc
index 04d264b..08e2a6e 100644
--- a/src/processor/stackwalker_x86_unittest.cc
+++ b/src/processor/stackwalker_x86_unittest.cc
@@ -36,6 +36,7 @@
 
 #include "breakpad_googletest_includes.h"
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/processor/basic_source_line_resolver.h"
 #include "google_breakpad/processor/call_stack.h"
@@ -55,7 +56,6 @@
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Label;
 using google_breakpad::test_assembler::Section;
-using std::string;
 using std::vector;
 using testing::_;
 using testing::Return;
@@ -69,7 +69,11 @@
       // Give the two modules reasonable standard locations and names
       // for tests to play with.
       module1(0x40000000, 0x10000, "module1", "version1"),
-      module2(0x50000000, 0x10000, "module2", "version2") {
+      module2(0x50000000, 0x10000, "module2", "version2"),
+      module3(0x771d0000, 0x180000, "module3", "version3"),
+      module4(0x75f90000, 0x46000, "module4", "version4"),
+      module5(0x75730000, 0x110000, "module5", "version5"),
+      module6(0x647f0000, 0x1ba8000, "module6", "version6") {
     // Identify the system as a Linux system.
     system_info.os = "Linux";
     system_info.os_short = "linux";
@@ -83,6 +87,10 @@
     // Create some modules with some stock debugging information.
     modules.Add(&module1);
     modules.Add(&module2);
+    modules.Add(&module3);
+    modules.Add(&module4);
+    modules.Add(&module5);
+    modules.Add(&module6);
 
     // By default, none of the modules have symbol info; call
     // SetModuleSymbols to override this.
@@ -93,9 +101,7 @@
   // Set the Breakpad symbol information that supplier should return for
   // MODULE to INFO.
   void SetModuleSymbols(MockCodeModule *module, const string &info) {
-    unsigned int buffer_size = info.size() + 1;
-    char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
-    strcpy(buffer, info.c_str());
+    char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info);
     EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
       .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
                             Return(MockSymbolSupplier::FOUND)));
@@ -122,6 +128,10 @@
   MockMemoryRegion stack_region;
   MockCodeModule module1;
   MockCodeModule module2;
+  MockCodeModule module3;
+  MockCodeModule module4;
+  MockCodeModule module5;
+  MockCodeModule module6;
   MockCodeModules modules;
   MockSymbolSupplier supplier;
   BasicSourceLineResolver resolver;
@@ -196,24 +206,28 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x4000c7a5U, frame0->instruction);
-  EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
-  EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
-  EXPECT_EQ(NULL, frame0->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x4000c7a5U, frame0->instruction);
+    EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
+    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+    EXPECT_EQ(NULL, frame0->windows_frame_info);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x40008679U, frame1->instruction + 1);
-  EXPECT_EQ(0x40008679U, frame1->context.eip);
-  EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x40008679U, frame1->instruction + 1);
+    EXPECT_EQ(0x40008679U, frame1->context.eip);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
 }
 
 // Walk a traditional frame, but use a bogus %ebp value, forcing a scan
@@ -247,30 +261,34 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x4000f49dU, frame0->instruction);
-  EXPECT_EQ(0x4000f49dU, frame0->context.eip);
-  EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
-  EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
-  EXPECT_EQ(NULL, frame0->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x4000f49dU, frame0->instruction);
+    EXPECT_EQ(0x4000f49dU, frame0->context.eip);
+    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+    EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
+    EXPECT_EQ(NULL, frame0->windows_frame_info);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
-  // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
-  // walker does not actually fetch the EBP after a scan (forcing the
-  // next frame to be scanned as well). But let's grandfather the existing
-  // behavior in for now.
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
-  EXPECT_EQ(0x4000129dU, frame1->context.eip);
-  EXPECT_EQ(0x80000014U, frame1->context.esp);
-  EXPECT_EQ(0xd43eed6eU, frame1->context.ebp);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+    // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
+    // walker does not actually fetch the EBP after a scan (forcing the
+    // next frame to be scanned as well). But let's grandfather the existing
+    // behavior in for now.
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
+    EXPECT_EQ(0x4000129dU, frame1->context.eip);
+    EXPECT_EQ(0x80000014U, frame1->context.esp);
+    EXPECT_EQ(0xd43eed6eU, frame1->context.ebp);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
 }
 
 // Force scanning for a return address a long way down the stack
@@ -304,30 +322,34 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x4000f49dU, frame0->instruction);
-  EXPECT_EQ(0x4000f49dU, frame0->context.eip);
-  EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
-  EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
-  EXPECT_EQ(NULL, frame0->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x4000f49dU, frame0->instruction);
+    EXPECT_EQ(0x4000f49dU, frame0->context.eip);
+    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+    EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
+    EXPECT_EQ(NULL, frame0->windows_frame_info);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
-  // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
-  // walker does not actually fetch the EBP after a scan (forcing the
-  // next frame to be scanned as well). But let's grandfather the existing
-  // behavior in for now.
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
-  EXPECT_EQ(0x4000129dU, frame1->context.eip);
-  EXPECT_EQ(0x80000064U, frame1->context.esp);
-  EXPECT_EQ(0xd43eed6eU, frame1->context.ebp);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+    // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
+    // walker does not actually fetch the EBP after a scan (forcing the
+    // next frame to be scanned as well). But let's grandfather the existing
+    // behavior in for now.
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
+    EXPECT_EQ(0x4000129dU, frame1->context.eip);
+    EXPECT_EQ(0x80000064U, frame1->context.esp);
+    EXPECT_EQ(0xd43eed6eU, frame1->context.ebp);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
 }
 
 // Use Windows frame data (a "STACK WIN 4" record, from a
@@ -371,32 +393,36 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x4000aa85U, frame0->instruction);
-  EXPECT_EQ(0x4000aa85U, frame0->context.eip);
-  EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
-  EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
-  EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x4000aa85U, frame0->instruction);
+    EXPECT_EQ(0x4000aa85U, frame0->context.eip);
+    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+    EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
+    EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP
-             | StackFrameX86::CONTEXT_VALID_EBX
-             | StackFrameX86::CONTEXT_VALID_ESI
-             | StackFrameX86::CONTEXT_VALID_EDI),
-            frame1->context_validity);
-  EXPECT_EQ(0x40001350U, frame1->instruction + 1);
-  EXPECT_EQ(0x40001350U, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
-  EXPECT_EQ(0x9068a878U, frame1->context.ebx);
-  EXPECT_EQ(0xa7120d1aU, frame1->context.esi);
-  EXPECT_EQ(0x630891beU, frame1->context.edi);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP
+               | StackFrameX86::CONTEXT_VALID_EBX
+               | StackFrameX86::CONTEXT_VALID_ESI
+               | StackFrameX86::CONTEXT_VALID_EDI),
+              frame1->context_validity);
+    EXPECT_EQ(0x40001350U, frame1->instruction + 1);
+    EXPECT_EQ(0x40001350U, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_EQ(0x9068a878U, frame1->context.ebx);
+    EXPECT_EQ(0xa7120d1aU, frame1->context.esi);
+    EXPECT_EQ(0x630891beU, frame1->context.edi);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
 }
 
 // Use Windows frame data (a "STACK WIN 4" record, from a
@@ -438,26 +464,30 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x4000aa85U, frame0->instruction);
-  EXPECT_EQ(0x4000aa85U, frame0->context.eip);
-  EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
-  EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
-  EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x4000aa85U, frame0->instruction);
+    EXPECT_EQ(0x4000aa85U, frame0->context.eip);
+    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+    EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
+    EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x5000129dU, frame1->instruction + 1);
-  EXPECT_EQ(0x5000129dU, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x5000129dU, frame1->instruction + 1);
+    EXPECT_EQ(0x5000129dU, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
 }
 
 // Use Windows frame data (a "STACK WIN 4" record, from a
@@ -516,56 +546,66 @@
   frames = call_stack.frames();
   ASSERT_EQ(3U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x40001004U, frame0->instruction);
-  EXPECT_EQ(0x40001004U, frame0->context.eip);
-  EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
-  EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
-  EXPECT_EQ(&module1, frame0->module);
-  EXPECT_EQ("module1::wheedle", frame0->function_name);
-  EXPECT_EQ(0x40001000U, frame0->function_base);
-  // The FUNC record for module1::wheedle should have produced a
-  // WindowsFrameInfo structure with only the parameter size valid.
-  ASSERT_TRUE(frame0->windows_frame_info != NULL);
-  EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
-            frame0->windows_frame_info->valid);
-  EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x40001004U, frame0->instruction);
+    EXPECT_EQ(0x40001004U, frame0->context.eip);
+    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+    EXPECT_EQ(&module1, frame0->module);
+    EXPECT_EQ("module1::wheedle", frame0->function_name);
+    EXPECT_EQ(0x40001000U, frame0->function_base);
+    // The FUNC record for module1::wheedle should have produced a
+    // WindowsFrameInfo structure with only the parameter size valid.
+    ASSERT_TRUE(frame0->windows_frame_info != NULL);
+    EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
+              frame0->windows_frame_info->valid);
+    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN,
+              frame0->windows_frame_info->type_);
+    EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x5000aa95U, frame1->instruction + 1);
-  EXPECT_EQ(0x5000aa95U, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_EQ(0x6fa902e0U, frame1->context.ebp);
-  EXPECT_EQ(&module2, frame1->module);
-  EXPECT_EQ("module2::whine", frame1->function_name);
-  EXPECT_EQ(0x5000aa85U, frame1->function_base);
-  ASSERT_TRUE(frame1->windows_frame_info != NULL);
-  EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
-  // This should not see the 0xbeef parameter size from the FUNC
-  // record, but should instead see the STACK WIN record.
-  EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x5000aa95U, frame1->instruction + 1);
+    EXPECT_EQ(0x5000aa95U, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(0x6fa902e0U, frame1->context.ebp);
+    EXPECT_EQ(&module2, frame1->module);
+    EXPECT_EQ("module2::whine", frame1->function_name);
+    EXPECT_EQ(0x5000aa85U, frame1->function_base);
+    ASSERT_TRUE(frame1->windows_frame_info != NULL);
+    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
+    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+              frame1->windows_frame_info->type_);
+    // This should not see the 0xbeef parameter size from the FUNC
+    // record, but should instead see the STACK WIN record.
+    EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
+  }
 
-  StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP
-             | StackFrameX86::CONTEXT_VALID_EBX),
-            frame2->context_validity);
-  EXPECT_EQ(0x2a179e38U, frame2->instruction + 1);
-  EXPECT_EQ(0x2a179e38U, frame2->context.eip);
-  EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
-  EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
-  EXPECT_EQ(0x2558c7f3U, frame2->context.ebx);
-  EXPECT_EQ(NULL, frame2->module);
-  EXPECT_EQ(NULL, frame2->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP
+               | StackFrameX86::CONTEXT_VALID_EBX),
+              frame2->context_validity);
+    EXPECT_EQ(0x2a179e38U, frame2->instruction + 1);
+    EXPECT_EQ(0x2a179e38U, frame2->context.eip);
+    EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
+    EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
+    EXPECT_EQ(0x2558c7f3U, frame2->context.ebx);
+    EXPECT_EQ(NULL, frame2->module);
+    EXPECT_EQ(NULL, frame2->windows_frame_info);
+  }
 }
 
 // Use Windows frame data (a "STACK WIN 4" record, from a
@@ -600,29 +640,33 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x40000c9cU, frame0->instruction);
-  EXPECT_EQ(0x40000c9cU, frame0->context.eip);
-  EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
-  EXPECT_EQ(0x2ae314cdU, frame0->context.ebp);
-  EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x40000c9cU, frame0->instruction);
+    EXPECT_EQ(0x40000c9cU, frame0->context.eip);
+    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+    EXPECT_EQ(0x2ae314cdU, frame0->context.ebp);
+    EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
-  // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
-  // does not actually fetch the EBP after a scan (forcing the next frame
-  // to be scanned as well). But let's grandfather the existing behavior in
-  // for now.
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x50007ce9U, frame1->instruction + 1);
-  EXPECT_EQ(0x50007ce9U, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_TRUE(frame1->windows_frame_info != NULL);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+    // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
+    // does not actually fetch the EBP after a scan (forcing the next frame
+    // to be scanned as well). But let's grandfather the existing behavior in
+    // for now.
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x50007ce9U, frame1->instruction + 1);
+    EXPECT_EQ(0x50007ce9U, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_TRUE(frame1->windows_frame_info != NULL);
+  }
 }
 
 // Use Windows frame data (a "STACK WIN 4" record, from a
@@ -679,30 +723,34 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x40000700U, frame0->instruction);
-  EXPECT_EQ(0x40000700U, frame0->context.eip);
-  EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
-  EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
-  EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x40000700U, frame0->instruction);
+    EXPECT_EQ(0x40000700U, frame0->context.eip);
+    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+    EXPECT_TRUE(frame0->windows_frame_info != NULL);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
-  // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
-  // walker does not actually fetch the EBP after a scan (forcing the
-  // next frame to be scanned as well). But let's grandfather the existing
-  // behavior in for now.
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x5000d000U, frame1->instruction + 1);
-  EXPECT_EQ(0x5000d000U, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
-  EXPECT_TRUE(frame1->windows_frame_info != NULL);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
+    // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
+    // walker does not actually fetch the EBP after a scan (forcing the
+    // next frame to be scanned as well). But let's grandfather the existing
+    // behavior in for now.
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x5000d000U, frame1->instruction + 1);
+    EXPECT_EQ(0x5000d000U, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_TRUE(frame1->windows_frame_info != NULL);
+  }
 }
 
 // Use Windows FrameTypeFPO data to walk a stack frame for a function that
@@ -742,35 +790,41 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x4000e8b8U, frame0->instruction);
-  EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
-  EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
-  EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); // unchanged from caller
-  EXPECT_EQ(&module1, frame0->module);
-  EXPECT_EQ("module1::discombobulated", frame0->function_name);
-  EXPECT_EQ(0x4000e8a8U, frame0->function_base);
-  // The STACK WIN record for module1::discombobulated should have
-  // produced a fully populated WindowsFrameInfo structure.
-  ASSERT_TRUE(frame0->windows_frame_info != NULL);
-  EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
-  EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x4000e8b8U, frame0->instruction);
+    EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
+    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); // unchanged from caller
+    EXPECT_EQ(&module1, frame0->module);
+    EXPECT_EQ("module1::discombobulated", frame0->function_name);
+    EXPECT_EQ(0x4000e8a8U, frame0->function_base);
+    // The STACK WIN record for module1::discombobulated should have
+    // produced a fully populated WindowsFrameInfo structure.
+    ASSERT_TRUE(frame0->windows_frame_info != NULL);
+    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
+              frame0->windows_frame_info->type_);
+    EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x40009b5bU, frame1->instruction + 1);
-  EXPECT_EQ(0x40009b5bU, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
-  EXPECT_EQ(&module1, frame1->module);
-  EXPECT_EQ("", frame1->function_name);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x40009b5bU, frame1->instruction + 1);
+    EXPECT_EQ(0x40009b5bU, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_EQ(&module1, frame1->module);
+    EXPECT_EQ("", frame1->function_name);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
 }
 
 // Use Windows FrameTypeFPO data to walk a stack frame for a function
@@ -812,36 +866,188 @@
   frames = call_stack.frames();
   ASSERT_EQ(2U, frames->size());
 
-  StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-  ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-  EXPECT_EQ(0x40009ab8U, frame0->instruction);
-  EXPECT_EQ(0x40009ab8U, frame0->context.eip);
-  EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
-  EXPECT_EQ(0xecbdd1a5, frame0->context.ebp);
-  EXPECT_EQ(&module1, frame0->module);
-  EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name);
-  EXPECT_EQ(0x40009aa8U, frame0->function_base);
-  // The STACK WIN record for module1::RaisedByTheAliens should have
-  // produced a fully populated WindowsFrameInfo structure.
-  ASSERT_TRUE(frame0->windows_frame_info != NULL);
-  EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
-  EXPECT_EQ("", frame0->windows_frame_info->program_string);
-  EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x40009ab8U, frame0->instruction);
+    EXPECT_EQ(0x40009ab8U, frame0->context.eip);
+    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+    EXPECT_EQ(0xecbdd1a5, frame0->context.ebp);
+    EXPECT_EQ(&module1, frame0->module);
+    EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name);
+    EXPECT_EQ(0x40009aa8U, frame0->function_base);
+    // The STACK WIN record for module1::RaisedByTheAliens should have
+    // produced a fully populated WindowsFrameInfo structure.
+    ASSERT_TRUE(frame0->windows_frame_info != NULL);
+    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
+              frame0->windows_frame_info->type_);
+    EXPECT_EQ("", frame0->windows_frame_info->program_string);
+    EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
+  }
 
-  StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-  EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
-  ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
-             | StackFrameX86::CONTEXT_VALID_ESP
-             | StackFrameX86::CONTEXT_VALID_EBP),
-            frame1->context_validity);
-  EXPECT_EQ(0x4000debeU, frame1->instruction + 1);
-  EXPECT_EQ(0x4000debeU, frame1->context.eip);
-  EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
-  EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
-  EXPECT_EQ(&module1, frame1->module);
-  EXPECT_EQ("", frame1->function_name);
-  EXPECT_EQ(NULL, frame1->windows_frame_info);
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x4000debeU, frame1->instruction + 1);
+    EXPECT_EQ(0x4000debeU, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_EQ(&module1, frame1->module);
+    EXPECT_EQ("", frame1->function_name);
+    EXPECT_EQ(NULL, frame1->windows_frame_info);
+  }
+}
+
+// This is a regression unit test which covers a bug which has to do with
+// FPO-optimized Windows system call stubs in the context frame.  There is
+// a more recent Windows system call dispatch mechanism which differs from
+// the one which is being tested here.  The newer system call dispatch
+// mechanism creates an extra context frame (KiFastSystemCallRet).
+TEST_F(GetCallerFrame, WindowsFPOSystemCall) {
+  SetModuleSymbols(&module3,  // ntdll.dll
+                   "PUBLIC 1f8ac c ZwWaitForSingleObject\n"
+                   "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n");
+  SetModuleSymbols(&module4,  // kernelbase.dll
+                   "PUBLIC 109f9 c WaitForSingleObjectEx\n"
+                   "PUBLIC 36590 0 _except_handler4\n"
+                   "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip "
+                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+                   "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
+                   "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip "
+                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 "
+                   ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
+  SetModuleSymbols(&module5,  // kernel32.dll
+                   "PUBLIC 11136 8 WaitForSingleObject\n"
+                   "PUBLIC 11151 c WaitForSingleObjectExImplementation\n"
+                   "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip "
+                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+                   "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
+                   "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip "
+                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+                   "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
+  SetModuleSymbols(&module6,  // chrome.dll
+                   "FILE 7038 some_file_name.h\n"
+                   "FILE 839776 some_file_name.cc\n"
+                   "FUNC 217fda 17 4 function_217fda\n"
+                   "217fda 4 102 839776\n"
+                   "FUNC 217ff1 a 4 function_217ff1\n"
+                   "217ff1 0 594 7038\n"
+                   "217ff1 a 596 7038\n"
+                   "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n");
+
+  Label frame0_esp, frame1_esp;
+  Label frame1_ebp, frame2_ebp, frame3_ebp;
+  stack_section.start() = 0x002ff290;
+  stack_section
+    .Mark(&frame0_esp)
+    .D32(0x771ef8c1)    // EIP in frame 0 (system call)
+    .D32(0x75fa0a91)    // return address of frame 0
+    .Mark(&frame1_esp)
+    .D32(0x000017b0)    // args to child
+    .D32(0x00000000)
+    .D32(0x002ff2d8)
+    .D32(0x88014a2e)
+    .D32(0x002ff364)
+    .D32(0x000017b0)
+    .D32(0x00000000)
+    .D32(0x00000024)
+    .D32(0x00000001)
+    .D32(0x00000000)
+    .D32(0x00000000)
+    .D32(0x00000000)
+    .D32(0x00000000)
+    .D32(0x00000000)
+    .D32(0x00000000)
+    .D32(0x00000000)
+    .D32(0x9e3b9800)
+    .D32(0xfffffff7)
+    .D32(0x00000000)
+    .D32(0x002ff2a4)
+    .D32(0x64a07ff1)    // random value to be confused with a return address
+    .D32(0x002ff8dc)
+    .D32(0x75fc6590)    // random value to be confused with a return address
+    .D32(0xfdd2c6ea)
+    .D32(0x00000000)
+    .Mark(&frame1_ebp)
+    .D32(frame2_ebp)    // Child EBP
+    .D32(0x75741194)    // return address of frame 1
+    .D32(0x000017b0)    // args to child
+    .D32(0x0036ee80)
+    .D32(0x00000000)
+    .D32(0x65bc7d14)
+    .Mark(&frame2_ebp)
+    .D32(frame3_ebp)    // Child EBP
+    .D32(0x75741148)    // return address of frame 2
+    .D32(0x000017b0)    // args to child
+    .D32(0x0036ee80)
+    .D32(0x00000000)
+    .Mark(&frame3_ebp)
+    .D32(0)             // saved %ebp (stack end)
+    .D32(0);            // saved %eip (stack end)
+
+  RegionFromSection();
+  raw_context.eip = 0x771ef8c1;  // in ntdll::ZwWaitForSingleObject
+  raw_context.esp = stack_section.start().Value();
+  ASSERT_TRUE(raw_context.esp == frame0_esp.Value());
+  raw_context.ebp = frame1_ebp.Value();
+
+  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+                        &supplier, &resolver);
+  ASSERT_TRUE(walker.Walk(&call_stack));
+  frames = call_stack.frames();
+
+  ASSERT_EQ(4U, frames->size());
+
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+    EXPECT_EQ(0x771ef8c1U, frame0->instruction);
+    EXPECT_EQ(0x771ef8c1U, frame0->context.eip);
+    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
+    EXPECT_EQ(&module3, frame0->module);
+    EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name);
+    // The STACK WIN record for module3!ZwWaitForSingleObject should have
+    // produced a fully populated WindowsFrameInfo structure.
+    ASSERT_TRUE(frame0->windows_frame_info != NULL);
+    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
+              frame0->windows_frame_info->type_);
+    EXPECT_EQ("", frame0->windows_frame_info->program_string);
+    EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
+  }
+
+  {  // To avoid reusing locals by mistake
+    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+               | StackFrameX86::CONTEXT_VALID_ESP
+               | StackFrameX86::CONTEXT_VALID_EBP),
+              frame1->context_validity);
+    EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1);
+    EXPECT_EQ(0x75fa0a91U, frame1->context.eip);
+    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+    EXPECT_EQ(&module4, frame1->module);
+    EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name);
+    // The STACK WIN record for module4!WaitForSingleObjectEx should have
+    // produced a fully populated WindowsFrameInfo structure.
+    ASSERT_TRUE(frame1->windows_frame_info != NULL);
+    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
+    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+              frame1->windows_frame_info->type_);
+    EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+              "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =",
+              frame1->windows_frame_info->program_string);
+    EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
+  }
 }
 
 struct CFIFixture: public StackwalkerX86Fixture {
@@ -897,32 +1103,36 @@
     frames = call_stack.frames();
     ASSERT_EQ(2U, frames->size());
 
-    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
-    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
-    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
-    EXPECT_EQ("enchiridion", frame0->function_name);
-    EXPECT_EQ(0x40004000U, frame0->function_base);
-    ASSERT_TRUE(frame0->windows_frame_info != NULL);
-    ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
-              frame0->windows_frame_info->valid);
-    ASSERT_TRUE(frame0->cfi_frame_info != NULL);
+    {  // To avoid reusing locals by mistake
+      StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+      EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+      ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+      EXPECT_EQ("enchiridion", frame0->function_name);
+      EXPECT_EQ(0x40004000U, frame0->function_base);
+      ASSERT_TRUE(frame0->windows_frame_info != NULL);
+      ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
+                frame0->windows_frame_info->valid);
+      ASSERT_TRUE(frame0->cfi_frame_info != NULL);
+    }
 
-    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
-    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
-    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
-               StackFrameX86::CONTEXT_VALID_ESP |
-               StackFrameX86::CONTEXT_VALID_EBP |
-               StackFrameX86::CONTEXT_VALID_EBX |
-               StackFrameX86::CONTEXT_VALID_ESI |
-               StackFrameX86::CONTEXT_VALID_EDI),
-              frame1->context_validity);
-    EXPECT_EQ(expected.eip, frame1->context.eip);
-    EXPECT_EQ(expected.esp, frame1->context.esp);
-    EXPECT_EQ(expected.ebp, frame1->context.ebp);
-    EXPECT_EQ(expected.ebx, frame1->context.ebx);
-    EXPECT_EQ(expected.esi, frame1->context.esi);
-    EXPECT_EQ(expected.edi, frame1->context.edi);
-    EXPECT_EQ("epictetus", frame1->function_name);
+    {  // To avoid reusing locals by mistake
+      StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+      EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+      ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+                 StackFrameX86::CONTEXT_VALID_ESP |
+                 StackFrameX86::CONTEXT_VALID_EBP |
+                 StackFrameX86::CONTEXT_VALID_EBX |
+                 StackFrameX86::CONTEXT_VALID_ESI |
+                 StackFrameX86::CONTEXT_VALID_EDI),
+                 frame1->context_validity);
+      EXPECT_EQ(expected.eip, frame1->context.eip);
+      EXPECT_EQ(expected.esp, frame1->context.esp);
+      EXPECT_EQ(expected.ebp, frame1->context.ebp);
+      EXPECT_EQ(expected.ebx, frame1->context.ebx);
+      EXPECT_EQ(expected.esi, frame1->context.esi);
+      EXPECT_EQ(expected.edi, frame1->context.edi);
+      EXPECT_EQ("epictetus", frame1->function_name);
+    }
   }
 
   // The values the stack walker should find for the caller's registers.
diff --git a/src/processor/static_address_map_unittest.cc b/src/processor/static_address_map_unittest.cc
index 5ef0345..12c735c 100644
--- a/src/processor/static_address_map_unittest.cc
+++ b/src/processor/static_address_map_unittest.cc
@@ -39,13 +39,14 @@
 #include <sstream>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "processor/address_map-inl.h"
 #include "processor/static_address_map-inl.h"
 #include "processor/simple_serializer-inl.h"
 #include "map_serializers-inl.h"
 
 typedef google_breakpad::StaticAddressMap<int, char> TestMap;
-typedef google_breakpad::AddressMap<int, std::string> AddrMap;
+typedef google_breakpad::AddressMap<int, string> AddrMap;
 
 class TestStaticAddressMap : public ::testing::Test {
  protected:
@@ -92,8 +93,8 @@
   void CompareRetrieveResult(int testcase, int target) {
     int address;
     int address_test;
-    std::string entry;
-    std::string entry_test;
+    string entry;
+    string entry_test;
     const char *entry_cstring = NULL;
     bool found;
     bool found_test;
@@ -147,7 +148,7 @@
   AddrMap addr_map[kNumberTestCases];
   TestMap test_map[kNumberTestCases];
   char *map_data[kNumberTestCases];
-  google_breakpad::AddressMapSerializer<int, std::string> serializer;
+  google_breakpad::AddressMapSerializer<int, string> serializer;
 };
 
 const int TestStaticAddressMap::testsize[] = {0, 1, 6, 1000};
diff --git a/src/processor/synth_minidump.h b/src/processor/synth_minidump.h
index 245afe6..531603a 100644
--- a/src/processor/synth_minidump.h
+++ b/src/processor/synth_minidump.h
@@ -114,6 +114,7 @@
 #include <string>
 
 #include "common/test_assembler.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "google_breakpad/common/minidump_format.h"
 
@@ -121,7 +122,6 @@
 
 namespace SynthMinidump {
 
-using std::string;
 using test_assembler::Endianness;
 using test_assembler::kBigEndian;
 using test_assembler::kLittleEndian;
diff --git a/src/processor/synth_minidump_unittest.cc b/src/processor/synth_minidump_unittest.cc
index 1ce34dd..4376933 100644
--- a/src/processor/synth_minidump_unittest.cc
+++ b/src/processor/synth_minidump_unittest.cc
@@ -36,6 +36,7 @@
 #include <string>
 
 #include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "processor/synth_minidump.h"
 #include "processor/synth_minidump_unittest_data.h"
@@ -50,11 +51,9 @@
 using google_breakpad::SynthMinidump::Stream;
 using google_breakpad::SynthMinidump::String;
 using google_breakpad::SynthMinidump::SystemInfo;
-using google_breakpad::SynthMinidump::Thread;
 using google_breakpad::test_assembler::kBigEndian;
 using google_breakpad::test_assembler::kLittleEndian;
 using google_breakpad::test_assembler::Label;
-using std::string;
 
 TEST(Section, Simple) {
   Dump dump(0);
@@ -168,11 +167,12 @@
   Memory stack(dump, 0xaad55a93cc3c0efcULL);
   stack.Append("stack contents");
   stack.Finish(0xe08cdbd1);
-  Thread thread(dump, 0x3d7ec360, stack, context,
-                0x3593f44d, // suspend count
-                0xab352b82, // priority class
-                0x2753d838, // priority
-                0xeb2de4be3f29e3e9ULL); // thread environment block
+  google_breakpad::SynthMinidump::Thread thread(
+      dump, 0x3d7ec360, stack, context,
+      0x3593f44d, // suspend count
+      0xab352b82, // priority class
+      0x2753d838, // priority
+      0xeb2de4be3f29e3e9ULL); // thread environment block
   string contents;
   ASSERT_TRUE(thread.GetContents(&contents));
   static const u_int8_t expected_bytes[] = {
diff --git a/src/processor/synth_minidump_unittest_data.h b/src/processor/synth_minidump_unittest_data.h
index 81995d2..be3bd70 100644
--- a/src/processor/synth_minidump_unittest_data.h
+++ b/src/processor/synth_minidump_unittest_data.h
@@ -247,22 +247,24 @@
   // context_flags
   0x591b9e6a,
   // iregs
-  0xa21594de,
-  0x820d8a25,
-  0xc4e133b2,
-  0x173a1c02,
-  0x105fb175,
-  0xe871793f,
-  0x5def70b3,
-  0xcee3a623,
-  0x7b3aa9b8,
-  0x52518537,
-  0x627012c5,
-  0x22723dcc,
-  0x16fcc971,
-  0x20988bcb,
-  0xf1ab806b,
-  0x99d5fc03,
+  {
+    0xa21594de,
+    0x820d8a25,
+    0xc4e133b2,
+    0x173a1c02,
+    0x105fb175,
+    0xe871793f,
+    0x5def70b3,
+    0xcee3a623,
+    0x7b3aa9b8,
+    0x52518537,
+    0x627012c5,
+    0x22723dcc,
+    0x16fcc971,
+    0x20988bcb,
+    0xf1ab806b,
+    0x99d5fc03,
+  },
   // cpsr
   0xb70df511,
   // float_save
@@ -270,47 +272,51 @@
     // fpscr
     0xa1e1f7ce1077e6b5ULL,
     // regs
-    0xbcb8d002eed7fbdeULL,
-    0x4dd26a43b96ae97fULL,
-    0x8eec22db8b31741cULL,
-    0xfd634bd7c5ad66a0ULL,
-    0x1681da0daeb3debeULL,
-    0x474a32bdf72d0b71ULL,
-    0xcaf464f8b1044834ULL,
-    0xcaa6592ae5c7582aULL,
-    0x4ee46889d877c3dbULL,
-    0xf8930cf301645cf5ULL,
-    0x4da7e9ebba27f7c7ULL,
-    0x69a7b02761944da3ULL,
-    0x2cda2b2e78195c06ULL,
-    0x66b227ab9b460a42ULL,
-    0x7e77e49e52ee0849ULL,
-    0xd62cd9663e76f255ULL,
-    0xe9370f082451514bULL,
-    0x50a1c674dd1b6029ULL,
-    0x405db4575829eac4ULL,
-    0x67b948764649eee7ULL,
-    0x93731885419229d4ULL,
-    0xdb0338bad72a4ce7ULL,
-    0xa0a451f996fca4c8ULL,
-    0xb4508ea668400a45ULL,
-    0xbff28c5c7a142423ULL,
-    0x4f31b42b96f3a431ULL,
-    0x2ce6789d4ea1ff37ULL,
-    0xfa150b52e4f82a3cULL,
-    0xe9ec40449e6ed4f3ULL,
-    0x5ceca87836fe2251ULL,
-    0x66f50de463ee238cULL,
-    0x42823efcd59ab511ULL,
+    {
+      0xbcb8d002eed7fbdeULL,
+      0x4dd26a43b96ae97fULL,
+      0x8eec22db8b31741cULL,
+      0xfd634bd7c5ad66a0ULL,
+      0x1681da0daeb3debeULL,
+      0x474a32bdf72d0b71ULL,
+      0xcaf464f8b1044834ULL,
+      0xcaa6592ae5c7582aULL,
+      0x4ee46889d877c3dbULL,
+      0xf8930cf301645cf5ULL,
+      0x4da7e9ebba27f7c7ULL,
+      0x69a7b02761944da3ULL,
+      0x2cda2b2e78195c06ULL,
+      0x66b227ab9b460a42ULL,
+      0x7e77e49e52ee0849ULL,
+      0xd62cd9663e76f255ULL,
+      0xe9370f082451514bULL,
+      0x50a1c674dd1b6029ULL,
+      0x405db4575829eac4ULL,
+      0x67b948764649eee7ULL,
+      0x93731885419229d4ULL,
+      0xdb0338bad72a4ce7ULL,
+      0xa0a451f996fca4c8ULL,
+      0xb4508ea668400a45ULL,
+      0xbff28c5c7a142423ULL,
+      0x4f31b42b96f3a431ULL,
+      0x2ce6789d4ea1ff37ULL,
+      0xfa150b52e4f82a3cULL,
+      0xe9ec40449e6ed4f3ULL,
+      0x5ceca87836fe2251ULL,
+      0x66f50de463ee238cULL,
+      0x42823efcd59ab511ULL,
+    },
     // extra
-    0xe9e14cd2,
-    0x865bb640,
-    0x9f3f0b3e,
-    0x94a71c52,
-    0x3c012f19,
-    0x6436637c,
-    0x46ccedcb,
-    0x7b341be7
+    {
+      0xe9e14cd2,
+      0x865bb640,
+      0x9f3f0b3e,
+      0x94a71c52,
+      0x3c012f19,
+      0x6436637c,
+      0x46ccedcb,
+      0x7b341be7,
+    }
   }
 };
 
diff --git a/src/processor/tokenize.cc b/src/processor/tokenize.cc
index 85f7782..e398c52 100644
--- a/src/processor/tokenize.cc
+++ b/src/processor/tokenize.cc
@@ -32,9 +32,10 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
-using std::string;
 using std::vector;
 
 bool Tokenize(char *line,
diff --git a/src/processor/tokenize.h b/src/processor/tokenize.h
index 1562b82..9ff571d 100644
--- a/src/processor/tokenize.h
+++ b/src/processor/tokenize.h
@@ -35,6 +35,8 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
+
 namespace google_breakpad {
 
 // Splits line into at most max_tokens tokens, separated by any of the
@@ -49,12 +51,12 @@
 // exact, as opposed to maximum, number of tokens.
 
 bool Tokenize(char *line,
-	      const char *separators,
-	      int max_tokens,
-	      std::vector<char*> *tokens);
+              const char *separators,
+              int max_tokens,
+              std::vector<char*> *tokens);
 // For convenience, since you need a char* to pass to Tokenize.
-// You can call StringToVector on a std::string, and use &vec[0].
-void StringToVector(const std::string &str, std::vector<char> &vec);
+// You can call StringToVector on a string, and use &vec[0].
+void StringToVector(const string &str, std::vector<char> &vec);
 
 }  // namespace google_breakpad
 
diff --git a/src/processor/windows_frame_info.h b/src/processor/windows_frame_info.h
index 067f3cf..8af4b3f 100644
--- a/src/processor/windows_frame_info.h
+++ b/src/processor/windows_frame_info.h
@@ -44,6 +44,7 @@
 #include <string>
 #include <vector>
 
+#include "common/using_std_string.h"
 #include "google_breakpad/common/breakpad_types.h"
 #include "processor/logging.h"
 #include "processor/tokenize.h"
@@ -72,7 +73,8 @@
     STACK_INFO_UNKNOWN = -1
   };
 
-  WindowsFrameInfo() : valid(VALID_NONE),
+  WindowsFrameInfo() : type_(STACK_INFO_UNKNOWN),
+                     valid(VALID_NONE),
                      prolog_size(0),
                      epilog_size(0),
                      parameter_size(0),
@@ -82,15 +84,17 @@
                      allocates_base_pointer(0),
                      program_string() {}
 
-  WindowsFrameInfo(u_int32_t set_prolog_size,
+  WindowsFrameInfo(StackInfoTypes type,
+                 u_int32_t set_prolog_size,
                  u_int32_t set_epilog_size,
                  u_int32_t set_parameter_size,
                  u_int32_t set_saved_register_size,
                  u_int32_t set_local_size,
                  u_int32_t set_max_stack_size,
                  int set_allocates_base_pointer,
-                 const std::string set_program_string)
-      : valid(VALID_ALL),
+                 const string set_program_string)
+      : type_(type),
+        valid(VALID_ALL),
         prolog_size(set_prolog_size),
         epilog_size(set_epilog_size),
         parameter_size(set_parameter_size),
@@ -104,7 +108,7 @@
   // a string. Returns NULL if parsing fails, or a new object
   // otherwise. type, rva and code_size are present in the STACK line,
   // but not the StackFrameInfo structure, so return them as outparams.
-  static WindowsFrameInfo *ParseFromString(const std::string string,
+  static WindowsFrameInfo *ParseFromString(const string string,
                                            int &type,
                                            u_int64_t &rva,
                                            u_int64_t &code_size) {
@@ -140,7 +144,8 @@
       allocates_base_pointer = strtoul(tokens[10], NULL, 16);
     }
 
-    return new WindowsFrameInfo(prolog_size,
+    return new WindowsFrameInfo(static_cast<StackInfoTypes>(type),
+                                prolog_size,
                                 epilog_size,
                                 parameter_size,
                                 saved_register_size,
@@ -152,6 +157,7 @@
 
   // CopyFrom makes "this" WindowsFrameInfo object identical to "that".
   void CopyFrom(const WindowsFrameInfo &that) {
+    type_ = that.type_;
     valid = that.valid;
     prolog_size = that.prolog_size;
     epilog_size = that.epilog_size;
@@ -166,10 +172,13 @@
   // Clears the WindowsFrameInfo object so that users will see it as though
   // it contains no information.
   void Clear() {
+    type_ = STACK_INFO_UNKNOWN;
     valid = VALID_NONE;
     program_string.erase();
   }
 
+  StackInfoTypes type_;
+
   // Identifies which fields in the structure are valid.  This is of
   // type Validity, but it is defined as an int because it's not
   // possible to OR values into an enumerated type.  Users must check
@@ -187,7 +196,7 @@
   // Only one of allocates_base_pointer or program_string will be valid.
   // If program_string is empty, use allocates_base_pointer.
   bool allocates_base_pointer;
-  std::string program_string;
+  string program_string;
 };
 
 }  // namespace google_breakpad
diff --git a/src/tools/linux/core2md/core2md.cc b/src/tools/linux/core2md/core2md.cc
index c8060b5..641496e 100644
--- a/src/tools/linux/core2md/core2md.cc
+++ b/src/tools/linux/core2md/core2md.cc
@@ -32,12 +32,24 @@
 #include <stdio.h>
 
 #include "client/linux/minidump_writer/minidump_writer.h"
+#include "client/linux/minidump_writer/linux_core_dumper.h"
+
+using google_breakpad::MappingList;
+using google_breakpad::LinuxCoreDumper;
 
 static int ShowUsage(const char* argv0) {
   fprintf(stderr, "Usage: %s <core file> <procfs dir> <output>\n", argv0);
   return 1;
 }
 
+bool WriteMinidumpFromCore(const char* filename,
+                           const char* core_path,
+                           const char* procfs_override) {
+  MappingList mappings;
+  LinuxCoreDumper dumper(0, core_path, procfs_override);
+  return google_breakpad::WriteMinidump(filename, mappings, &dumper);
+}
+
 int main(int argc, char *argv[]) {
   if (argc != 4) {
     return ShowUsage(argv[0]);
@@ -46,9 +58,9 @@
   const char* core_file = argv[1];
   const char* procfs_dir = argv[2];
   const char* minidump_file = argv[3];
-  if (!google_breakpad::WriteMinidumpFromCore(minidump_file,
-                                              core_file,
-                                              procfs_dir)) {
+  if (!WriteMinidumpFromCore(minidump_file,
+                             core_file,
+                             procfs_dir)) {
     fprintf(stderr, "Unable to generate minidump.\n");
     return 1;
   }
diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc
index 0a0343f..5b20175 100644
--- a/src/tools/linux/md2core/minidump-2-core.cc
+++ b/src/tools/linux/md2core/minidump-2-core.cc
@@ -48,12 +48,11 @@
 
 #include "client/linux/minidump_writer/minidump_extension_linux.h"
 #include "common/linux/memory_mapped_file.h"
-#include "google_breakpad/common/minidump_cpu_x86.h"
 #include "google_breakpad/common/minidump_format.h"
+#include "processor/scoped_ptr.h"
 #include "third_party/lss/linux_syscall_support.h"
 #include "tools/linux/md2core/minidump_memory_range.h"
 
-
 #if __WORDSIZE == 64
   #define ELF_CLASS ELFCLASS64
 #else
@@ -1101,9 +1100,9 @@
   }
 
   if (note_align) {
-    char scratch[note_align];
-    memset(scratch, 0, sizeof(scratch));
-    if (!writea(1, scratch, sizeof(scratch)))
+    google_breakpad::scoped_array<char> scratch(new char[note_align]);
+    memset(scratch.get(), 0, note_align);
+    if (!writea(1, scratch.get(), note_align))
       return 1;
   }