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 ¤t = 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 §ion = ".debug_frame")
+ Reporter(const string &filename,
+ const string §ion = ".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 = §ions[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, ®ister_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 §ion) {
+ void LoadedSection(const string §ion) {
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;
}