diff --git a/Makefile.am b/Makefile.am index 6a6ca3fc..22948492 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,6 +71,7 @@ src_client_linux_libbreakpad_client_a_SOURCES = \ 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 \ @@ -313,6 +314,7 @@ src_client_linux_linux_client_unittest_LDADD = \ src/client/minidump_file_writer.o \ src/common/convert_UTF.o \ src/common/md5.o \ + src/common/linux/elf_core_dump.o \ src/common/linux/file_id.o \ src/common/linux/guid_creator.o \ src/common/linux/memory_mapped_file.o \ @@ -380,6 +382,8 @@ src_common_dumper_unittest_SOURCES = \ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols_unittest.cc \ + src/common/linux/elf_core_dump.cc \ + src/common/linux/elf_core_dump_unittest.cc \ src/common/linux/elf_symbols_to_module.cc \ src/common/linux/elf_symbols_to_module_unittest.cc \ src/common/linux/memory_mapped_file.cc \ @@ -390,6 +394,8 @@ src_common_dumper_unittest_SOURCES = \ src/common/linux/file_id_unittest.cc \ src/common/linux/safe_readlink.cc \ src/common/linux/safe_readlink_unittest.cc \ + src/common/linux/tests/crash_generator.cc \ + src/common/tests/file_utils.cc \ src/testing/gtest/src/gtest-all.cc \ src/testing/gtest/src/gtest_main.cc \ src/testing/src/gmock-all.cc @@ -398,7 +404,9 @@ src_common_dumper_unittest_CPPFLAGS = \ -I$(top_srcdir)/src/testing/include \ -I$(top_srcdir)/src/testing/gtest/include \ -I$(top_srcdir)/src/testing/gtest \ - -I$(top_srcdir)/src/testing + -I$(top_srcdir)/src/testing \ + $(PTHREAD_CFLAGS) +src_common_dumper_unittest_LDADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) endif src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \ diff --git a/Makefile.in b/Makefile.in index 7fdae4f4..5e0bb6e7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -174,7 +174,8 @@ am__src_client_linux_libbreakpad_client_a_SOURCES_DIST = \ 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/file_id.cc src/common/linux/guid_creator.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 \ src/common/linux/safe_readlink.cc am__dirstamp = $(am__leading_dot)dirstamp @@ -186,6 +187,7 @@ am__dirstamp = $(am__leading_dot)dirstamp @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) \ @@ -441,6 +443,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols_unittest.cc \ + src/common/linux/elf_core_dump.cc \ + src/common/linux/elf_core_dump_unittest.cc \ src/common/linux/elf_symbols_to_module.cc \ src/common/linux/elf_symbols_to_module_unittest.cc \ src/common/linux/memory_mapped_file.cc \ @@ -451,6 +455,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \ src/common/linux/file_id_unittest.cc \ src/common/linux/safe_readlink.cc \ src/common/linux/safe_readlink_unittest.cc \ + src/common/linux/tests/crash_generator.cc \ + src/common/tests/file_utils.cc \ src/testing/gtest/src/gtest-all.cc \ src/testing/gtest/src/gtest_main.cc \ src/testing/src/gmock-all.cc @@ -479,6 +485,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_core_dump.$(OBJEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-memory_mapped_file.$(OBJEXT) \ @@ -489,12 +497,17 @@ am__src_common_dumper_unittest_SOURCES_DIST = \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-file_id_unittest.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-safe_readlink.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.$(OBJEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/src_common_dumper_unittest-crash_generator.$(OBJEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/testing/gtest/src/src_common_dumper_unittest-gtest-all.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/testing/gtest/src/src_common_dumper_unittest-gtest_main.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/testing/src/src_common_dumper_unittest-gmock-all.$(OBJEXT) src_common_dumper_unittest_OBJECTS = \ $(am_src_common_dumper_unittest_OBJECTS) -src_common_dumper_unittest_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_DEPENDENCIES = \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1) am__src_common_test_assembler_unittest_SOURCES_DIST = \ src/common/test_assembler.cc src/common/test_assembler.h \ src/common/test_assembler_unittest.cc \ @@ -1193,6 +1206,7 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3) @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 \ @@ -1363,6 +1377,7 @@ TESTS_ENVIRONMENT = @LINUX_HOST_TRUE@ src/client/minidump_file_writer.o \ @LINUX_HOST_TRUE@ src/common/convert_UTF.o \ @LINUX_HOST_TRUE@ src/common/md5.o \ +@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.o \ @LINUX_HOST_TRUE@ src/common/linux/file_id.o \ @LINUX_HOST_TRUE@ src/common/linux/guid_creator.o \ @LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.o \ @@ -1428,6 +1443,8 @@ TESTS_ENVIRONMENT = @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \ @@ -1438,6 +1455,8 @@ TESTS_ENVIRONMENT = @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/safe_readlink_unittest.cc \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/testing/gtest/src/gtest-all.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/testing/gtest/src/gtest_main.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/testing/src/gmock-all.cc @@ -1447,8 +1466,10 @@ TESTS_ENVIRONMENT = @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/include \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/gtest/include \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/gtest \ -@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS) +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_LDADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \ @LINUX_HOST_TRUE@ src/testing/gtest/src/gtest-all.cc \ @LINUX_HOST_TRUE@ src/testing/gtest/src/gtest_main.cc \ @@ -2183,6 +2204,9 @@ src/common/linux/$(am__dirstamp): 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): \ @@ -2516,6 +2540,12 @@ src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT): \ src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) +src/common/linux/src_common_dumper_unittest-elf_core_dump.$(OBJEXT): \ + src/common/linux/$(am__dirstamp) \ + src/common/linux/$(DEPDIR)/$(am__dirstamp) +src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.$(OBJEXT): \ + src/common/linux/$(am__dirstamp) \ + src/common/linux/$(DEPDIR)/$(am__dirstamp) src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) @@ -2546,6 +2576,24 @@ src/common/linux/src_common_dumper_unittest-safe_readlink.$(OBJEXT): \ src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) +src/common/linux/tests/$(am__dirstamp): + @$(MKDIR_P) src/common/linux/tests + @: > src/common/linux/tests/$(am__dirstamp) +src/common/linux/tests/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/common/linux/tests/$(DEPDIR) + @: > src/common/linux/tests/$(DEPDIR)/$(am__dirstamp) +src/common/linux/tests/src_common_dumper_unittest-crash_generator.$(OBJEXT): \ + src/common/linux/tests/$(am__dirstamp) \ + src/common/linux/tests/$(DEPDIR)/$(am__dirstamp) +src/common/tests/$(am__dirstamp): + @$(MKDIR_P) src/common/tests + @: > src/common/tests/$(am__dirstamp) +src/common/tests/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/common/tests/$(DEPDIR) + @: > src/common/tests/$(DEPDIR)/$(am__dirstamp) +src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT): \ + src/common/tests/$(am__dirstamp) \ + src/common/tests/$(DEPDIR)/$(am__dirstamp) src/testing/gtest/src/src_common_dumper_unittest-gtest-all.$(OBJEXT): \ src/testing/gtest/src/$(am__dirstamp) \ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) @@ -2991,6 +3039,7 @@ mostlyclean-compile: -rm -f src/common/dwarf_line_to_module.$(OBJEXT) -rm -f src/common/language.$(OBJEXT) -rm -f src/common/linux/dump_symbols.$(OBJEXT) + -rm -f src/common/linux/elf_core_dump.$(OBJEXT) -rm -f src/common/linux/elf_symbols_to_module.$(OBJEXT) -rm -f src/common/linux/file_id.$(OBJEXT) -rm -f src/common/linux/guid_creator.$(OBJEXT) @@ -2999,6 +3048,8 @@ mostlyclean-compile: -rm -f src/common/linux/safe_readlink.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT) + -rm -f src/common/linux/src_common_dumper_unittest-elf_core_dump.$(OBJEXT) + -rm -f src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-file_id.$(OBJEXT) @@ -3009,6 +3060,7 @@ mostlyclean-compile: -rm -f src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-synth_elf.$(OBJEXT) -rm -f src/common/linux/src_common_dumper_unittest-synth_elf_unittest.$(OBJEXT) + -rm -f src/common/linux/tests/src_common_dumper_unittest-crash_generator.$(OBJEXT) -rm -f src/common/md5.$(OBJEXT) -rm -f src/common/module.$(OBJEXT) -rm -f src/common/src_client_linux_linux_client_unittest-memory_unittest.$(OBJEXT) @@ -3038,6 +3090,7 @@ mostlyclean-compile: -rm -f src/common/stabs_reader.$(OBJEXT) -rm -f src/common/stabs_to_module.$(OBJEXT) -rm -f src/common/string_conversion.$(OBJEXT) + -rm -f src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT) -rm -f src/processor/address_map_unittest.$(OBJEXT) -rm -f src/processor/basic_code_modules.$(OBJEXT) -rm -f src/processor/basic_source_line_resolver.$(OBJEXT) @@ -3227,6 +3280,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dump_symbols.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_core_dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_symbols_to_module.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/file_id.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/guid_creator.Po@am__quote@ @@ -3235,6 +3289,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/safe_readlink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Po@am__quote@ @@ -3245,6 +3301,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/address_map_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_code_modules.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver.Po@am__quote@ @@ -3953,6 +4011,34 @@ src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj: src/commo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj `if test -f 'src/common/linux/dump_symbols_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/dump_symbols_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/dump_symbols_unittest.cc'; fi` +src/common/linux/src_common_dumper_unittest-elf_core_dump.o: src/common/linux/elf_core_dump.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.o `test -f 'src/common/linux/elf_core_dump.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/elf_core_dump.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.o `test -f 'src/common/linux/elf_core_dump.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump.cc + +src/common/linux/src_common_dumper_unittest-elf_core_dump.obj: src/common/linux/elf_core_dump.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.obj `if test -f 'src/common/linux/elf_core_dump.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/elf_core_dump.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.obj `if test -f 'src/common/linux/elf_core_dump.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump.cc'; fi` + +src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o: src/common/linux/elf_core_dump_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o `test -f 'src/common/linux/elf_core_dump_unittest.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/elf_core_dump_unittest.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o `test -f 'src/common/linux/elf_core_dump_unittest.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump_unittest.cc + +src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj: src/common/linux/elf_core_dump_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj `if test -f 'src/common/linux/elf_core_dump_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/elf_core_dump_unittest.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj `if test -f 'src/common/linux/elf_core_dump_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump_unittest.cc'; fi` + src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o: src/common/linux/elf_symbols_to_module.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o `test -f 'src/common/linux/elf_symbols_to_module.cc' || echo '$(srcdir)/'`src/common/linux/elf_symbols_to_module.cc @am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Po @@ -4093,6 +4179,34 @@ src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj: src/comm @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj `if test -f 'src/common/linux/safe_readlink_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/safe_readlink_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/safe_readlink_unittest.cc'; fi` +src/common/linux/tests/src_common_dumper_unittest-crash_generator.o: src/common/linux/tests/crash_generator.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/tests/src_common_dumper_unittest-crash_generator.o -MD -MP -MF src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.o `test -f 'src/common/linux/tests/crash_generator.cc' || echo '$(srcdir)/'`src/common/linux/tests/crash_generator.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/tests/crash_generator.cc' object='src/common/linux/tests/src_common_dumper_unittest-crash_generator.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.o `test -f 'src/common/linux/tests/crash_generator.cc' || echo '$(srcdir)/'`src/common/linux/tests/crash_generator.cc + +src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj: src/common/linux/tests/crash_generator.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj -MD -MP -MF src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj `if test -f 'src/common/linux/tests/crash_generator.cc'; then $(CYGPATH_W) 'src/common/linux/tests/crash_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/tests/crash_generator.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/tests/crash_generator.cc' object='src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj `if test -f 'src/common/linux/tests/crash_generator.cc'; then $(CYGPATH_W) 'src/common/linux/tests/crash_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/tests/crash_generator.cc'; fi` + +src/common/tests/src_common_dumper_unittest-file_utils.o: src/common/tests/file_utils.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_common_dumper_unittest-file_utils.o -MD -MP -MF src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo -c -o src/common/tests/src_common_dumper_unittest-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/tests/file_utils.cc' object='src/common/tests/src_common_dumper_unittest-file_utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_common_dumper_unittest-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc + +src/common/tests/src_common_dumper_unittest-file_utils.obj: src/common/tests/file_utils.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_common_dumper_unittest-file_utils.obj -MD -MP -MF src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo -c -o src/common/tests/src_common_dumper_unittest-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/tests/file_utils.cc' object='src/common/tests/src_common_dumper_unittest-file_utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_common_dumper_unittest-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi` + src/testing/gtest/src/src_common_dumper_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_common_dumper_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_common_dumper_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_common_dumper_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc @am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_common_dumper_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_common_dumper_unittest-gtest-all.Po @@ -5542,6 +5656,10 @@ distclean-generic: -rm -f src/common/dwarf/$(am__dirstamp) -rm -f src/common/linux/$(DEPDIR)/$(am__dirstamp) -rm -f src/common/linux/$(am__dirstamp) + -rm -f src/common/linux/tests/$(DEPDIR)/$(am__dirstamp) + -rm -f src/common/linux/tests/$(am__dirstamp) + -rm -f src/common/tests/$(DEPDIR)/$(am__dirstamp) + -rm -f src/common/tests/$(am__dirstamp) -rm -f src/processor/$(DEPDIR)/$(am__dirstamp) -rm -f src/processor/$(am__dirstamp) -rm -f src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) @@ -5568,7 +5686,7 @@ clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ 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/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(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/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/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 @@ -5616,7 +5734,7 @@ installcheck-am: 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/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(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/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/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/src/common/linux/elf_core_dump.cc b/src/common/linux/elf_core_dump.cc new file mode 100644 index 00000000..0e7db7b1 --- /dev/null +++ b/src/common/linux/elf_core_dump.cc @@ -0,0 +1,179 @@ +// 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. + +// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump. +// See elf_core_dump.h for details. + +#include "common/linux/elf_core_dump.h" + +#include +#include + +namespace google_breakpad { + +// Implementation of ElfCoreDump::Note. + +ElfCoreDump::Note::Note() {} + +ElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {} + +bool ElfCoreDump::Note::IsValid() const { + return GetHeader() != NULL; +} + +const ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const { + return content_.GetData(0); +} + +ElfCoreDump::Word ElfCoreDump::Note::GetType() const { + const Nhdr* header = GetHeader(); + // 0 is not being used as a NOTE type. + return header ? header->n_type : 0; +} + +MemoryRange ElfCoreDump::Note::GetName() const { + const Nhdr* header = GetHeader(); + if (header) { + return content_.Subrange(sizeof(Nhdr), header->n_namesz); + } + return MemoryRange(); +} + +MemoryRange ElfCoreDump::Note::GetDescription() const { + const Nhdr* header = GetHeader(); + if (header) { + return content_.Subrange(AlignedSize(sizeof(Nhdr) + header->n_namesz), + header->n_descsz); + } + return MemoryRange(); +} + +ElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const { + MemoryRange next_content; + const Nhdr* header = GetHeader(); + if (header) { + size_t next_offset = AlignedSize(sizeof(Nhdr) + header->n_namesz); + next_offset = AlignedSize(next_offset + header->n_descsz); + next_content = + content_.Subrange(next_offset, content_.length() - next_offset); + } + return Note(next_content); +} + +// static +size_t ElfCoreDump::Note::AlignedSize(size_t size) { + size_t mask = sizeof(Word) - 1; + return (size + mask) & ~mask; +} + + +// Implementation of ElfCoreDump. + +ElfCoreDump::ElfCoreDump() {} + +ElfCoreDump::ElfCoreDump(const MemoryRange& content) + : content_(content) { +} + +void ElfCoreDump::SetContent(const MemoryRange& content) { + content_ = content; +} + +bool ElfCoreDump::IsValid() const { + const Ehdr* header = GetHeader(); + return (header && + header->e_ident[0] == ELFMAG0 && + header->e_ident[1] == ELFMAG1 && + header->e_ident[2] == ELFMAG2 && + header->e_ident[3] == ELFMAG3 && + header->e_ident[4] == kClass && + header->e_version == EV_CURRENT && + header->e_type == ET_CORE); +} + +const ElfCoreDump::Ehdr* ElfCoreDump::GetHeader() const { + return content_.GetData(0); +} + +const ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const { + const Ehdr* header = GetHeader(); + if (header) { + return reinterpret_cast(content_.GetArrayElement( + header->e_phoff, header->e_phentsize, index)); + } + return NULL; +} + +const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType( + Word type) const { + for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) { + const Phdr* program = GetProgramHeader(i); + if (program->p_type == type) { + return program; + } + } + return NULL; +} + +unsigned ElfCoreDump::GetProgramHeaderCount() const { + const Ehdr* header = GetHeader(); + return header ? header->e_phnum : 0; +} + +bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) { + for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) { + const Phdr* program = GetProgramHeader(i); + if (program->p_type != PT_LOAD) + continue; + + size_t offset_in_segment = virtual_address - program->p_vaddr; + if (virtual_address >= program->p_vaddr && + offset_in_segment < program->p_filesz) { + const void* data = + content_.GetData(program->p_offset + offset_in_segment, length); + if (data) { + memcpy(buffer, data, length); + return true; + } + } + } + return false; +} + +ElfCoreDump::Note ElfCoreDump::GetFirstNote() const { + MemoryRange note_content; + const Phdr* program_header = GetFirstProgramHeaderOfType(PT_NOTE); + if (program_header) { + note_content = content_.Subrange(program_header->p_offset, + program_header->p_filesz); + } + return Note(note_content); +} + +} // namespace google_breakpad diff --git a/src/common/linux/elf_core_dump.h b/src/common/linux/elf_core_dump.h new file mode 100644 index 00000000..dd846f09 --- /dev/null +++ b/src/common/linux/elf_core_dump.h @@ -0,0 +1,153 @@ +// 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. + +// elf_core_dump.h: Define the google_breakpad::ElfCoreDump class, which +// encapsulates an ELF core dump file mapped into memory. + +#ifndef COMMON_LINUX_ELF_CORE_DUMP_H_ +#define COMMON_LINUX_ELF_CORE_DUMP_H_ + +#include +#if !defined(__ANDROID__) +#include +#endif +#include + +#include "common/memory_range.h" +#if defined(__ANDROID__) +#include "common/linux/android_link.h" +#endif + +namespace google_breakpad { + +// A class encapsulating an ELF core dump file mapped into memory, which +// provides methods for accessing program headers and the note section. +class ElfCoreDump { + public: + // ELF types based on the value of __WORDSIZE. + typedef ElfW(Ehdr) Ehdr; + typedef ElfW(Nhdr) Nhdr; + typedef ElfW(Phdr) Phdr; + typedef ElfW(Word) Word; + typedef ElfW(Addr) Addr; +#if __WORDSIZE == 32 + static const int kClass = ELFCLASS32; +#elif __WORDSIZE == 64 + static const int kClass = ELFCLASS64; +#else +#error "Unsupported __WORDSIZE for ElfCoreDump." +#endif + + // A class encapsulating the note content in a core dump, which provides + // methods for accessing the name and description of a note. + class Note { + public: + Note(); + + // Constructor that takes the note content from |content|. + explicit Note(const MemoryRange& content); + + // Returns true if this note is valid, i,e. a note header is found in + // |content_|, or false otherwise. + bool IsValid() const; + + // Returns the note header, or NULL if no note header is found in + // |content_|. + const Nhdr* GetHeader() const; + + // Returns the note type, or 0 if no note header is found in |content_|. + Word GetType() const; + + // Returns a memory range covering the note name, or an empty range + // if no valid note name is found in |content_|. + MemoryRange GetName() const; + + // Returns a memory range covering the note description, or an empty + // range if no valid note description is found in |content_|. + MemoryRange GetDescription() const; + + // Returns the note following this note, or an empty note if no valid + // note is found after this note. + Note GetNextNote() const; + + private: + // Returns the size in bytes round up to the word alignment, specified + // for the note section, of a given size in bytes. + static size_t AlignedSize(size_t size); + + // Note content. + MemoryRange content_; + }; + + ElfCoreDump(); + + // Constructor that takes the core dump content from |content|. + explicit ElfCoreDump(const MemoryRange& content); + + // Sets the core dump content to |content|. + void SetContent(const MemoryRange& content); + + // Returns true if a valid ELF header in the core dump, or false otherwise. + bool IsValid() const; + + // Returns the ELF header in the core dump, or NULL if no ELF header + // is found in |content_|. + const Ehdr* GetHeader() const; + + // Returns the |index|-th program header in the core dump, or NULL if no + // ELF header is found in |content_| or |index| is out of bounds. + const Phdr* GetProgramHeader(unsigned index) const; + + // Returns the first program header of |type| in the core dump, or NULL if + // no ELF header is found in |content_| or no program header of |type| is + // found. + const Phdr* GetFirstProgramHeaderOfType(Word type) const; + + // Returns the number of program headers in the core dump, or 0 if no + // ELF header is found in |content_|. + unsigned GetProgramHeaderCount() const; + + // Copies |length| bytes of data starting at |virtual_address| in the core + // dump to |buffer|. |buffer| should be a valid pointer to a buffer of at + // least |length| bytes. Returns true if the data to be copied is found in + // the core dump, or false otherwise. + bool CopyData(void* buffer, Addr virtual_address, size_t length); + + // Returns the first note found in the note section of the core dump, or + // an empty note if no note is found. + Note GetFirstNote() const; + + private: + // Core dump content. + MemoryRange content_; +}; + +} // namespace google_breakpad + +#endif // COMMON_LINUX_ELF_CORE_DUMP_H_ diff --git a/src/common/linux/elf_core_dump_unittest.cc b/src/common/linux/elf_core_dump_unittest.cc new file mode 100644 index 00000000..324e57b6 --- /dev/null +++ b/src/common/linux/elf_core_dump_unittest.cc @@ -0,0 +1,238 @@ +// 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. + +// elf_core_dump_unittest.cc: Unit tests for google_breakpad::ElfCoreDump. + +#include + +#include +#include + +#include "breakpad_googletest_includes.h" +#include "common/linux/elf_core_dump.h" +#include "common/linux/memory_mapped_file.h" +#include "common/tests/file_utils.h" +#include "common/linux/tests/crash_generator.h" + +using google_breakpad::AutoTempDir; +using google_breakpad::CrashGenerator; +using google_breakpad::ElfCoreDump; +using google_breakpad::MemoryMappedFile; +using google_breakpad::MemoryRange; +using google_breakpad::WriteFile; +using std::set; +using std::string; + +TEST(ElfCoreDumpTest, DefaultConstructor) { + ElfCoreDump core; + EXPECT_FALSE(core.IsValid()); + EXPECT_EQ(NULL, core.GetHeader()); + EXPECT_EQ(0, core.GetProgramHeaderCount()); + EXPECT_EQ(NULL, core.GetProgramHeader(0)); + EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD)); + EXPECT_FALSE(core.GetFirstNote().IsValid()); +} + +TEST(ElfCoreDumpTest, TestElfHeader) { + ElfCoreDump::Ehdr header; + memset(&header, 0, sizeof(header)); + + AutoTempDir temp_dir; + string core_path = temp_dir.path() + "/core"; + const char* core_file = core_path.c_str(); + MemoryMappedFile mapped_core_file; + ElfCoreDump core; + + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header) - 1)); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + EXPECT_EQ(NULL, core.GetHeader()); + EXPECT_EQ(0, core.GetProgramHeaderCount()); + EXPECT_EQ(NULL, core.GetProgramHeader(0)); + EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD)); + EXPECT_FALSE(core.GetFirstNote().IsValid()); + + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_ident[0] = ELFMAG0; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_ident[1] = ELFMAG1; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_ident[2] = ELFMAG2; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_ident[3] = ELFMAG3; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_ident[4] = ElfCoreDump::kClass; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_version = EV_CURRENT; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_FALSE(core.IsValid()); + + header.e_type = ET_CORE; + ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); + ASSERT_TRUE(mapped_core_file.Map(core_file)); + core.SetContent(mapped_core_file.content()); + EXPECT_TRUE(core.IsValid()); +} + +TEST(ElfCoreDumpTest, ValidCoreFile) { + CrashGenerator crash_generator; + if (!crash_generator.HasDefaultCorePattern()) { + fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped"); + return; + } + + const unsigned kNumOfThreads = 3; + const unsigned kCrashThread = 1; + const int kCrashSignal = SIGABRT; + ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread, + kCrashSignal)); + pid_t expected_crash_thread_id = crash_generator.GetThreadId(kCrashThread); + set expected_thread_ids; + for (unsigned i = 0; i < kNumOfThreads; ++i) { + expected_thread_ids.insert(crash_generator.GetThreadId(i)); + } + + MemoryMappedFile mapped_core_file; + ASSERT_TRUE(mapped_core_file.Map(crash_generator.GetCoreFilePath().c_str())); + + ElfCoreDump core; + core.SetContent(mapped_core_file.content()); + EXPECT_TRUE(core.IsValid()); + + // Based on write_note_info() in linux/kernel/fs/binfmt_elf.c, notes are + // ordered as follows (NT_PRXFPREG and NT_386_TLS are i386 specific): + // Thread Name Type + // ------------------------------------------------------------------- + // 1st thread CORE NT_PRSTATUS + // process-wide CORE NT_PRPSINFO + // process-wide CORE NT_AUXV + // 1st thread CORE NT_FPREGSET + // 1st thread LINUX NT_PRXFPREG + // 1st thread LINUX NT_386_TLS + // + // 2nd thread CORE NT_PRSTATUS + // 2nd thread CORE NT_FPREGSET + // 2nd thread LINUX NT_PRXFPREG + // 2nd thread LINUX NT_386_TLS + // + // 3rd thread CORE NT_PRSTATUS + // 3rd thread CORE NT_FPREGSET + // 3rd thread LINUX NT_PRXFPREG + // 3rd thread LINUX NT_386_TLS + + size_t num_nt_prpsinfo = 0; + size_t num_nt_prstatus = 0; + size_t num_nt_fpregset = 0; + size_t num_nt_prxfpreg = 0; + set actual_thread_ids; + ElfCoreDump::Note note = core.GetFirstNote(); + while (note.IsValid()) { + MemoryRange name = note.GetName(); + MemoryRange description = note.GetDescription(); + EXPECT_FALSE(name.IsEmpty()); + EXPECT_FALSE(description.IsEmpty()); + + switch (note.GetType()) { + case NT_PRPSINFO: { + EXPECT_TRUE(description.data() != NULL); + EXPECT_EQ(sizeof(elf_prpsinfo), description.length()); + ++num_nt_prpsinfo; + break; + } + case NT_PRSTATUS: { + EXPECT_TRUE(description.data() != NULL); + EXPECT_EQ(sizeof(elf_prstatus), description.length()); + const elf_prstatus* status = description.GetData(0); + actual_thread_ids.insert(status->pr_pid); + if (num_nt_prstatus == 0) { + EXPECT_EQ(expected_crash_thread_id, status->pr_pid); + EXPECT_EQ(kCrashSignal, status->pr_info.si_signo); + } + ++num_nt_prstatus; + break; + } +#if defined(__i386) || defined(__x86_64) + case NT_FPREGSET: { + EXPECT_TRUE(description.data() != NULL); + EXPECT_EQ(sizeof(user_fpregs_struct), description.length()); + ++num_nt_fpregset; + break; + } +#endif +#if defined(__i386) + case NT_PRXFPREG: { + EXPECT_TRUE(description.data() != NULL); + EXPECT_EQ(sizeof(user_fpxregs_struct), description.length()); + ++num_nt_prxfpreg; + break; + } +#endif + default: + break; + } + note = note.GetNextNote(); + } + + 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) + EXPECT_EQ(kNumOfThreads, num_nt_fpregset); +#endif +#if defined(__i386) + EXPECT_EQ(kNumOfThreads, num_nt_prxfpreg); +#endif +} diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc index 8a3129fb..cf89bca9 100644 --- a/src/common/linux/memory_mapped_file_unittest.cc +++ b/src/common/linux/memory_mapped_file_unittest.cc @@ -40,32 +40,15 @@ #include "common/linux/eintr_wrapper.h" #include "common/linux/memory_mapped_file.h" #include "common/tests/auto_tempdir.h" +#include "common/tests/file_utils.h" using google_breakpad::AutoTempDir; using google_breakpad::MemoryMappedFile; +using google_breakpad::WriteFile; using std::string; namespace { -bool WriteFile(const string& path, const void* buffer, size_t buffer_size) { - int fd = - HANDLE_EINTR(open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU)); - if (fd == -1) { - perror("open"); - return false; - } - - bool ok = true; - if (buffer && buffer_size > 0) { - if (HANDLE_EINTR(write(fd, buffer, buffer_size) != buffer_size)) { - perror("write"); - ok = false; - } - } - close(fd); - return ok; -} - class MemoryMappedFileTest : public testing::Test { protected: void ExpectNoMappedData(const MemoryMappedFile& mapped_file) { @@ -102,7 +85,7 @@ TEST_F(MemoryMappedFileTest, MapNonexistentFile) { TEST_F(MemoryMappedFileTest, MapEmptyFile) { AutoTempDir temp_dir; string test_file = temp_dir.path() + "/empty_file"; - ASSERT_TRUE(WriteFile(test_file, NULL, 0)); + ASSERT_TRUE(WriteFile(test_file.c_str(), NULL, 0)); { MemoryMappedFile mapped_file(test_file.c_str()); @@ -124,7 +107,7 @@ TEST_F(MemoryMappedFileTest, MapNonEmptyFile) { AutoTempDir temp_dir; string test_file = temp_dir.path() + "/test_file"; - ASSERT_TRUE(WriteFile(test_file, data, data_size)); + ASSERT_TRUE(WriteFile(test_file.c_str(), data, data_size)); { MemoryMappedFile mapped_file(test_file.c_str()); @@ -159,8 +142,8 @@ TEST_F(MemoryMappedFileTest, RemapAfterMap) { AutoTempDir temp_dir; string test_file1 = temp_dir.path() + "/test_file1"; string test_file2 = temp_dir.path() + "/test_file2"; - ASSERT_TRUE(WriteFile(test_file1, data1, data1_size)); - ASSERT_TRUE(WriteFile(test_file2, data2, data2_size)); + ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size)); + ASSERT_TRUE(WriteFile(test_file2.c_str(), data2, data2_size)); { MemoryMappedFile mapped_file(test_file1.c_str()); diff --git a/src/common/linux/tests/crash_generator.cc b/src/common/linux/tests/crash_generator.cc new file mode 100644 index 00000000..3ef40dbd --- /dev/null +++ b/src/common/linux/tests/crash_generator.cc @@ -0,0 +1,206 @@ +// 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. + +// crash_generator.cc: Implement google_breakpad::CrashGenerator. +// See crash_generator.h for details. + +#include "common/linux/tests/crash_generator.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common/linux/eintr_wrapper.h" +#include "common/tests/auto_tempdir.h" +#include "common/tests/file_utils.h" + +namespace { + +struct ThreadData { + pthread_t thread; + pthread_barrier_t* barrier; + pid_t* thread_id_ptr; +}; + +// Core file size limit set to 1 MB, which is big enough for test purposes. +const rlim_t kCoreSizeLimit = 1024 * 1024; + +void *thread_function(void *data) { + ThreadData* thread_data = reinterpret_cast(data); + volatile pid_t thread_id = syscall(__NR_gettid); + *(thread_data->thread_id_ptr) = thread_id; + int result = pthread_barrier_wait(thread_data->barrier); + if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) { + exit(1); + } + while (true) { + pthread_yield(); + } +} + +} // namespace + +namespace google_breakpad { + +CrashGenerator::CrashGenerator() + : shared_memory_(NULL), + shared_memory_size_(0) { +} + +CrashGenerator::~CrashGenerator() { + UnmapSharedMemory(); +} + +bool CrashGenerator::HasDefaultCorePattern() const { + char buffer[8]; + ssize_t buffer_size = sizeof(buffer); + return ReadFile("/proc/sys/kernel/core_pattern", buffer, &buffer_size) && + buffer_size == 5 && memcmp(buffer, "core", 4) == 0; +} + +std::string CrashGenerator::GetCoreFilePath() const { + return temp_dir_.path() + "/core"; +} + +pid_t CrashGenerator::GetThreadId(unsigned index) const { + return reinterpret_cast(shared_memory_)[index]; +} + +pid_t* CrashGenerator::GetThreadIdPointer(unsigned index) { + return reinterpret_cast(shared_memory_) + index; +} + +bool CrashGenerator::MapSharedMemory(size_t memory_size) { + if (!UnmapSharedMemory()) + return false; + + void* mapped_memory = mmap(0, memory_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (mapped_memory == MAP_FAILED) + return false; + + memset(mapped_memory, 0, memory_size); + shared_memory_ = mapped_memory; + shared_memory_size_ = memory_size; + return true; +} + +bool CrashGenerator::UnmapSharedMemory() { + if (!shared_memory_) + return true; + + if (munmap(shared_memory_, shared_memory_size_) == 0) { + shared_memory_ = NULL; + shared_memory_size_ = 0; + return true; + } + return false; +} + +bool CrashGenerator::SetCoreFileSizeLimit(rlim_t limit) const { + struct rlimit limits = { limit, limit }; + return setrlimit(RLIMIT_CORE, &limits) == 0; +} + +bool CrashGenerator::CreateChildCrash( + unsigned num_threads, unsigned crash_thread, int crash_signal) { + if (num_threads == 0 || crash_thread >= num_threads) + return false; + + if (!MapSharedMemory(num_threads * sizeof(pid_t))) + return false; + + pid_t pid = fork(); + if (pid == 0) { + if (chdir(temp_dir_.path().c_str()) == 0 && + SetCoreFileSizeLimit(kCoreSizeLimit)) { + CreateThreadsInChildProcess(num_threads); + kill(*GetThreadIdPointer(crash_thread), crash_signal); + } + exit(1); + } + + int status; + if (HANDLE_EINTR(waitpid(pid, &status, 0)) == -1 || + !WIFSIGNALED(status) || WTERMSIG(status) != crash_signal) + return false; + + return true; +} + +void CrashGenerator::CreateThreadsInChildProcess(unsigned num_threads) { + *GetThreadIdPointer(0) = getpid(); + + if (num_threads <= 1) + return; + + // This method does not clean up any pthread resource, as the process + // is expected to be killed anyway. + ThreadData* thread_data = new ThreadData[num_threads]; + + // Create detached threads so that we do not worry about pthread_join() + // later being called or not. + pthread_attr_t thread_attributes; + if (pthread_attr_init(&thread_attributes) != 0 || + pthread_attr_setdetachstate(&thread_attributes, + PTHREAD_CREATE_DETACHED) != 0) { + exit(1); + } + + pthread_barrier_t thread_barrier; + if (pthread_barrier_init(&thread_barrier, NULL, num_threads) != 0) { + exit(1); + } + + for (unsigned i = 1; i < num_threads; ++i) { + thread_data[i].barrier = &thread_barrier; + thread_data[i].thread_id_ptr = GetThreadIdPointer(i); + if (pthread_create(&thread_data[i].thread, &thread_attributes, + thread_function, &thread_data[i]) != 0) { + exit(1); + } + } + + int result = pthread_barrier_wait(&thread_barrier); + if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) { + exit(1); + } + + pthread_barrier_destroy(&thread_barrier); + pthread_attr_destroy(&thread_attributes); + delete[] thread_data; +} + +} // namespace google_breakpad diff --git a/src/common/linux/tests/crash_generator.h b/src/common/linux/tests/crash_generator.h new file mode 100644 index 00000000..c88a8920 --- /dev/null +++ b/src/common/linux/tests/crash_generator.h @@ -0,0 +1,108 @@ +// 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. + +// crash_generator.h: Define the google_breakpad::CrashGenerator class, +// which is used to generate a crash (and a core dump file) for testing. + +#ifndef COMMON_LINUX_TESTS_CRASH_GENERATOR_H_ +#define COMMON_LINUX_TESTS_CRASH_GENERATOR_H_ + +#include + +#include + +#include "common/tests/auto_tempdir.h" + +namespace google_breakpad { + +// A utility class for generating a crash (and a core dump file) for +// testing. It creates a child process with the specified number of +// threads, which is then termainated by the specified signal. A core +// dump file is expected to be created upon the termination of the child +// process, which can then be used for testing code that processes core +// dump files. +class CrashGenerator { + public: + CrashGenerator(); + + ~CrashGenerator(); + + // Returns true if a core dump file named 'core' will be generated in + // the current directory for a test that produces a crash by checking + // if /proc/sys/kernel/core_pattern has the default value 'core'. + bool HasDefaultCorePattern() const; + + // Sets the maximum size of core dump file (both the soft and hard limit) + // to |limit| bytes. Returns true on success. + bool SetCoreFileSizeLimit(rlim_t limit) const; + + // Returns the expected path of the core dump file. + std::string GetCoreFilePath() 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 + // a signal with number |crash_signal| to the |crash_thread|-th thread. + // Returns true on success. + bool CreateChildCrash(unsigned num_threads, unsigned crash_thread, + int crash_signal); + + // Creates |num_threads| threads in the child process. + void CreateThreadsInChildProcess(unsigned num_threads); + + // Returns the thread ID of the |index|-th thread in the child process. + // This method does not validate |index|. + pid_t GetThreadId(unsigned index) const; + + private: + // Creates a shared memory of |memory_size| bytes for communicating thread + // IDs between the parent and child process. Returns true on success. + bool MapSharedMemory(size_t memory_size); + + // Releases any shared memory created by MapSharedMemory(). Returns true on + // success. + bool UnmapSharedMemory(); + + // Returns the pointer to the thread ID of the |index|-th thread in the child + // process. This method does not validate |index|. + pid_t* GetThreadIdPointer(unsigned index); + + // Temporary directory in which a core file is generated. + AutoTempDir temp_dir_; + + // Shared memory for communicating thread IDs between the parent and + // child process. + void* shared_memory_; + + // Number of bytes mapped for |shared_memory_|. + size_t shared_memory_size_; +}; + +} // namespace google_breakpad + +#endif // COMMON_LINUX_TESTS_CRASH_GENERATOR_H_ diff --git a/src/common/tests/auto_tempdir.h b/src/common/tests/auto_tempdir.h index e78d7391..ccfd81bc 100644 --- a/src/common/tests/auto_tempdir.h +++ b/src/common/tests/auto_tempdir.h @@ -59,9 +59,9 @@ class AutoTempDir { DeleteRecursively(path_); } - const std::string& path() { - return path_; - } + const std::string& path() const { + return path_; + } private: void DeleteRecursively(const std::string& path) { diff --git a/src/common/tests/file_utils.cc b/src/common/tests/file_utils.cc new file mode 100644 index 00000000..0d9b04ad --- /dev/null +++ b/src/common/tests/file_utils.cc @@ -0,0 +1,97 @@ +// 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. + +// file_utils.cc: Implement utility functions for file manipulation. +// See file_utils.h for details. + +#include +#include +#include +#include + +#include "common/linux/eintr_wrapper.h" +#include "common/tests/file_utils.h" + +namespace google_breakpad { + +bool ReadFile(const char* path, void* buffer, ssize_t* buffer_size) { + int fd = HANDLE_EINTR(open(path, O_RDONLY)); + if (fd == -1) { + perror("open"); + return false; + } + + bool ok = true; + if (buffer && buffer_size && *buffer_size > 0) { + memset(buffer, 0, sizeof(*buffer_size)); + *buffer_size = HANDLE_EINTR(read(fd, buffer, *buffer_size)); + if (*buffer_size == -1) { + perror("read"); + ok = false; + } + } + if (HANDLE_EINTR(close(fd)) == -1) { + perror("close"); + ok = false; + } + return ok; +} + +bool WriteFile(const char* path, const void* buffer, size_t buffer_size) { + int fd = HANDLE_EINTR(open(path, O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU)); + if (fd == -1) { + perror("open"); + return false; + } + + bool ok = true; + if (buffer) { + size_t bytes_written_total = 0; + ssize_t bytes_written_partial = 0; + const char* data = reinterpret_cast(buffer); + while (bytes_written_total < buffer_size) { + bytes_written_partial = + HANDLE_EINTR(write(fd, data + bytes_written_total, + buffer_size - bytes_written_total)); + if (bytes_written_partial < 0) { + perror("write"); + ok = false; + break; + } + bytes_written_total += bytes_written_partial; + } + } + if (HANDLE_EINTR(close(fd)) == -1) { + perror("close"); + ok = false; + } + return ok; +} + +} // namespace google_breakpad diff --git a/src/common/tests/file_utils.h b/src/common/tests/file_utils.h new file mode 100644 index 00000000..52e8b009 --- /dev/null +++ b/src/common/tests/file_utils.h @@ -0,0 +1,49 @@ +// 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. + +// file_utils.h: Define utility functions for file manipulation, which +// are used for testing. + +#ifndef COMMON_TESTS_FILE_UTILS_H_ +#define COMMON_TESTS_FILE_UTILS_H_ + +namespace google_breakpad { + +// Reads the content of a file at |path| into |buffer|. |buffer_size| specifies +// the size of |buffer| in bytes and returns the number of bytes read from the +// file on success. Returns true on success. +bool ReadFile(const char* path, void* buffer, ssize_t* buffer_size); + +// Writes |buffer_size| bytes of the content in |buffer| to a file at |path|. +// Returns true on success. +bool WriteFile(const char* path, const void* buffer, size_t buffer_size); + +} // namespace google_breakpad + +#endif // COMMON_TESTS_FILE_UTILS_H_