From 33c135a16fb1d8869af561aacfa23a3b1fb53c07 Mon Sep 17 00:00:00 2001 From: "benchan@chromium.org" Date: Wed, 21 Dec 2011 22:33:21 +0000 Subject: [PATCH] Replace MMappedRange with MinidumpMemoryRange. This patch is part of a bigger patch that helps merging the breakpad code with the modified version in Chromium OS. The MemoryRange class was added in r895 (http://breakpad.appspot.com/332001), which is largely based on MMappedRange but generalized to be used in other code. However, MemoryRange does not support minidump data structures. This patch adds a MinidumpMemoryRange class that extends MemoryRange to handle minidump data structures, which can then replace MMappedRange. As with MemoryRange, MinidumpMemoryRange is unit tested. BUG=455 TEST=Tested the following: 1. Build on 32-bit and 64-bit Linux with gcc 4.4.3 and gcc 4.6. 2. Build on Mac OS X 10.6.8 with gcc 4.2 and clang 3.0 (with latest gmock). 3. All unit tests pass. 4. Run minidump-2-core to covnert a minidump file to a core file. Review URL: http://breakpad.appspot.com/335001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@898 4c0a9323-5329-0410-9bdc-e9ce6186880e --- Makefile.am | 16 +- Makefile.in | 111 +++++++- src/common/memory_range.h | 6 - src/tools/linux/md2core/minidump-2-core.cc | 166 ++++------- .../linux/md2core/minidump_memory_range.h | 89 ++++++ .../md2core/minidump_memory_range_unittest.cc | 258 ++++++++++++++++++ 6 files changed, 523 insertions(+), 123 deletions(-) create mode 100644 src/tools/linux/md2core/minidump_memory_range.h create mode 100644 src/tools/linux/md2core/minidump_memory_range_unittest.cc diff --git a/Makefile.am b/Makefile.am index 47e7676f..6a6ca3fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -255,7 +255,8 @@ check_PROGRAMS += \ if !DISABLE_TOOLS check_PROGRAMS += \ - src/common/dumper_unittest + src/common/dumper_unittest \ + src/tools/linux/md2core/minidump_2_core_unittest endif endif LINUX_HOST @@ -399,6 +400,19 @@ src_common_dumper_unittest_CPPFLAGS = \ -I$(top_srcdir)/src/testing/gtest \ -I$(top_srcdir)/src/testing endif + +src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \ + src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ + src/testing/src/gmock-all.cc \ + src/tools/linux/md2core/minidump_memory_range_unittest.cc +src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/testing/include \ + -I$(top_srcdir)/src/testing/gtest/include \ + -I$(top_srcdir)/src/testing/gtest \ + -I$(top_srcdir)/src/testing + endif LINUX_HOST if !DISABLE_PROCESSOR diff --git a/Makefile.in b/Makefile.in index 785233ca..7fdae4f4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -114,7 +114,8 @@ check_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ @LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__append_9 = \ -@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dumper_unittest +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dumper_unittest \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_2_core_unittest @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__append_10 = \ @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@ src/processor/stackwalker_selftest @@ -377,7 +378,8 @@ src_third_party_libdisasm_libdisasm_a_OBJECTS = \ @DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86_unittest$(EXEEXT) \ @DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump_unittest$(EXEEXT) @LINUX_HOST_TRUE@am__EXEEXT_5 = src/client/linux/linux_client_unittest$(EXEEXT) -@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_6 = src/common/dumper_unittest$(EXEEXT) +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_6 = src/common/dumper_unittest$(EXEEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT) @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__EXEEXT_7 = src/processor/stackwalker_selftest$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__src_client_linux_linux_client_unittest_SOURCES_DIST = \ @@ -924,6 +926,17 @@ am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST = \ src_tools_linux_md2core_minidump_2_core_OBJECTS = \ $(am_src_tools_linux_md2core_minidump_2_core_OBJECTS) src_tools_linux_md2core_minidump_2_core_LDADD = $(LDADD) +am__src_tools_linux_md2core_minidump_2_core_unittest_SOURCES_DIST = \ + src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ + src/testing/src/gmock-all.cc \ + src/tools/linux/md2core/minidump_memory_range_unittest.cc +@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS = src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.$(OBJEXT) \ +@LINUX_HOST_TRUE@ src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.$(OBJEXT) \ +@LINUX_HOST_TRUE@ src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.$(OBJEXT) \ +@LINUX_HOST_TRUE@ src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT) +src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS = $(am_src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) +src_tools_linux_md2core_minidump_2_core_unittest_LDADD = $(LDADD) am__src_tools_linux_symupload_minidump_upload_SOURCES_DIST = \ src/common/linux/http_upload.cc \ src/tools/linux/symupload/minidump_upload.cc @@ -995,6 +1008,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \ $(src_processor_synth_minidump_unittest_SOURCES) \ $(src_tools_linux_dump_syms_dump_syms_SOURCES) \ $(src_tools_linux_md2core_minidump_2_core_SOURCES) \ + $(src_tools_linux_md2core_minidump_2_core_unittest_SOURCES) \ $(src_tools_linux_symupload_minidump_upload_SOURCES) \ $(src_tools_linux_symupload_sym_upload_SOURCES) DIST_SOURCES = \ @@ -1032,6 +1046,7 @@ DIST_SOURCES = \ $(am__src_processor_synth_minidump_unittest_SOURCES_DIST) \ $(am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST) \ $(am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST) \ + $(am__src_tools_linux_md2core_minidump_2_core_unittest_SOURCES_DIST) \ $(am__src_tools_linux_symupload_minidump_upload_SOURCES_DIST) \ $(am__src_tools_linux_symupload_sym_upload_SOURCES_DIST) DATA = $(dist_doc_DATA) @@ -1434,6 +1449,19 @@ TESTS_ENVIRONMENT = @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/gtest \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing +@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 \ +@LINUX_HOST_TRUE@ src/testing/src/gmock-all.cc \ +@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_memory_range_unittest.cc + +@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \ +@LINUX_HOST_TRUE@ -I$(top_srcdir)/src \ +@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/include \ +@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/gtest/include \ +@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/gtest \ +@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing + @DISABLE_PROCESSOR_FALSE@src_processor_address_map_unittest_SOURCES = \ @DISABLE_PROCESSOR_FALSE@ src/processor/address_map_unittest.cc @@ -2897,6 +2925,21 @@ src/tools/linux/md2core/minidump-2-core.$(OBJEXT): \ src/tools/linux/md2core/minidump-2-core$(EXEEXT): $(src_tools_linux_md2core_minidump_2_core_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_DEPENDENCIES) src/tools/linux/md2core/$(am__dirstamp) @rm -f src/tools/linux/md2core/minidump-2-core$(EXEEXT) $(CXXLINK) $(src_tools_linux_md2core_minidump_2_core_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_LDADD) $(LIBS) +src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.$(OBJEXT): \ + src/testing/src/$(am__dirstamp) \ + src/testing/src/$(DEPDIR)/$(am__dirstamp) +src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT): \ + src/tools/linux/md2core/$(am__dirstamp) \ + src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp) +src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT): $(src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_unittest_DEPENDENCIES) src/tools/linux/md2core/$(am__dirstamp) + @rm -f src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT) + $(CXXLINK) $(src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_unittest_LDADD) $(LIBS) src/common/linux/http_upload.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) @@ -3082,6 +3125,8 @@ mostlyclean-compile: -rm -f src/testing/gtest/src/src_processor_static_range_map_unittest-gtest-all.$(OBJEXT) -rm -f src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.$(OBJEXT) -rm -f src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.$(OBJEXT) + -rm -f src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.$(OBJEXT) + -rm -f src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.$(OBJEXT) -rm -f src/testing/src/src_client_linux_linux_client_unittest-gmock-all.$(OBJEXT) -rm -f src/testing/src/src_common_dumper_unittest-gmock-all.$(OBJEXT) -rm -f src/testing/src/src_common_test_assembler_unittest-gmock-all.$(OBJEXT) @@ -3102,6 +3147,7 @@ mostlyclean-compile: -rm -f src/testing/src/src_processor_static_map_unittest-gmock-all.$(OBJEXT) -rm -f src/testing/src/src_processor_static_range_map_unittest-gmock-all.$(OBJEXT) -rm -f src/testing/src/src_processor_synth_minidump_unittest-gmock-all.$(OBJEXT) + -rm -f src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.$(OBJEXT) -rm -f src/third_party/libdisasm/ia32_implicit.$(OBJEXT) -rm -f src/third_party/libdisasm/ia32_insn.$(OBJEXT) -rm -f src/third_party/libdisasm/ia32_invariant.$(OBJEXT) @@ -3118,6 +3164,7 @@ mostlyclean-compile: -rm -f src/third_party/libdisasm/x86_operand_list.$(OBJEXT) -rm -f src/tools/linux/dump_syms/dump_syms.$(OBJEXT) -rm -f src/tools/linux/md2core/minidump-2-core.$(OBJEXT) + -rm -f src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT) -rm -f src/tools/linux/symupload/minidump_upload.$(OBJEXT) -rm -f src/tools/linux/symupload/sym_upload.$(OBJEXT) @@ -3285,6 +3332,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_static_range_map_unittest-gtest-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_common_dumper_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_common_test_assembler_unittest-gmock-all.Po@am__quote@ @@ -3305,6 +3354,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_static_map_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_static_range_map_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_implicit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_insn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_invariant.Po@am__quote@ @@ -3321,6 +3371,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_operand_list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/dump_syms/$(DEPDIR)/dump_syms.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/md2core/$(DEPDIR)/minidump-2-core.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/symupload/$(DEPDIR)/minidump_upload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/symupload/$(DEPDIR)/sym_upload.Po@am__quote@ @@ -5077,6 +5128,62 @@ src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj: src/proc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi` + +src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_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_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc + +src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj: src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` + +src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc + +src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` + +src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o: src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc + +src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj: src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` + +src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o: src/tools/linux/md2core/minidump_memory_range_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o -MD -MP -MF src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o `test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc' || echo '$(srcdir)/'`src/tools/linux/md2core/minidump_memory_range_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tools/linux/md2core/minidump_memory_range_unittest.cc' object='src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o `test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc' || echo '$(srcdir)/'`src/tools/linux/md2core/minidump_memory_range_unittest.cc + +src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj: src/tools/linux/md2core/minidump_memory_range_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj -MD -MP -MF src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj `if test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; then $(CYGPATH_W) 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/linux/md2core/minidump_memory_range_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tools/linux/md2core/minidump_memory_range_unittest.cc' object='src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj `if test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; then $(CYGPATH_W) 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/linux/md2core/minidump_memory_range_unittest.cc'; fi` install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" diff --git a/src/common/memory_range.h b/src/common/memory_range.h index 0c81d1ee..86bd08c9 100644 --- a/src/common/memory_range.h +++ b/src/common/memory_range.h @@ -45,12 +45,6 @@ namespace google_breakpad { // access of a subrange of the memory. Its implemementation does not // allocate memory or call into libc functions, and is thus safer to use // in a crashed environment. -// -// TODO(benchan): This class is largely based on the MMappedRange class -// in tools/linux/md2core/minidump-2-core.cc, but generalized for use in -// other code. Provide a variant of MemoryRange with methods for handling -// Minidump data structures in order to replace MMappedRange in -// minidump-2-core.cc. class MemoryRange { public: MemoryRange() : data_(NULL), length_(0) {} diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index ddefecc0..0a0343fb 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -48,9 +48,10 @@ #include "client/linux/minidump_writer/minidump_extension_linux.h" #include "common/linux/memory_mapped_file.h" -#include "google_breakpad/common/minidump_format.h" #include "google_breakpad/common/minidump_cpu_x86.h" +#include "google_breakpad/common/minidump_format.h" #include "third_party/lss/linux_syscall_support.h" +#include "tools/linux/md2core/minidump_memory_range.h" #if __WORDSIZE == 64 @@ -76,6 +77,7 @@ #endif using google_breakpad::MemoryMappedFile; +using google_breakpad::MinidumpMemoryRange; static const MDRVA kInvalidMDRVA = static_cast(-1); static bool verbose; @@ -106,63 +108,6 @@ writea(int fd, const void* idata, size_t length) { return true; } -// A range of a mmaped file. -class MMappedRange { - public: - MMappedRange(const void* data, size_t length) - : data_(reinterpret_cast(data)), - length_(length) { - } - - // Get an object of |length| bytes at |offset| and return a pointer to it - // unless it's out of bounds. - const void* GetObject(size_t offset, size_t length) const { - if (offset + length < offset) - return NULL; - if (offset + length > length_) - return NULL; - return data_ + offset; - } - - // Get element |index| of an array of objects of length |length| starting at - // |offset| bytes. Return NULL if out of bounds. - const void* GetArrayElement(size_t offset, size_t length, - unsigned index) const { - const size_t element_offset = offset + index * length; - return GetObject(element_offset, length); - } - - // Get a zero-terminated string. This method only works correctly for ASCII - // characters and does not convert between UTF-16 and UTF-8. - const std::string GetString(size_t offset) const { - const MDString* s = (const MDString*) GetObject(offset, sizeof(MDString)); - const u_int16_t* buf = &s->buffer[0]; - std::string str; - for (unsigned i = 0; i < s->length && buf[i]; ++i) { - str.push_back(buf[i]); - } - return str; - } - - // Return a new range which is a subset of this range. - MMappedRange Subrange(const MDLocationDescriptor& location) const { - if (location.rva > length_ || - location.rva + location.data_size < location.rva || - location.rva + location.data_size > length_) { - return MMappedRange(NULL, 0); - } - - return MMappedRange(data_ + location.rva, location.data_size); - } - - const uint8_t* data() const { return data_; } - size_t length() const { return length_; } - - private: - const uint8_t* const data_; - const size_t length_; -}; - /* Dynamically determines the byte sex of the system. Returns non-zero * for big-endian machines. */ @@ -290,9 +235,9 @@ U16(const uint8_t* data) { } static void -ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { - const MDRawContextX86* rawregs = - (const MDRawContextX86*) range.GetObject(0, sizeof(MDRawContextX86)); +ParseThreadRegisters(CrashedProcess::Thread* thread, + const MinidumpMemoryRange& range) { + const MDRawContextX86* rawregs = range.GetData(0); thread->regs.ebx = rawregs->ebx; thread->regs.ecx = rawregs->ecx; @@ -336,9 +281,9 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { } #elif defined(__x86_64__) static void -ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { - const MDRawContextAMD64* rawregs = - (const MDRawContextAMD64*) range.GetObject(0, sizeof(MDRawContextAMD64)); +ParseThreadRegisters(CrashedProcess::Thread* thread, + const MinidumpMemoryRange& range) { + const MDRawContextAMD64* rawregs = range.GetData(0); thread->regs.r15 = rawregs->r15; thread->regs.r14 = rawregs->r14; @@ -384,10 +329,9 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { #endif static void -ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange& full_file) { - const uint32_t num_threads = - *(const uint32_t*) range.GetObject(0, sizeof(uint32_t)); +ParseThreadList(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { + const uint32_t num_threads = *range.GetData(0); if (verbose) { fprintf(stderr, "MD_THREAD_LIST_STREAM:\n" @@ -399,11 +343,11 @@ ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, CrashedProcess::Thread thread; memset(&thread, 0, sizeof(thread)); const MDRawThread* rawthread = - (MDRawThread*) range.GetArrayElement(sizeof(uint32_t), - sizeof(MDRawThread), i); + range.GetArrayElement(sizeof(uint32_t), i); thread.tid = rawthread->thread_id; thread.stack_addr = rawthread->stack.start_of_memory_range; - MMappedRange stack_range = full_file.Subrange(rawthread->stack.memory); + MinidumpMemoryRange stack_range = + full_file.Subrange(rawthread->stack.memory); thread.stack = stack_range.data(); thread.stack_length = rawthread->stack.memory.data_size; @@ -415,10 +359,9 @@ ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, } static void -ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange &full_file) { - const MDRawSystemInfo* sysinfo = - (MDRawSystemInfo*) range.GetObject(0, sizeof(MDRawSystemInfo)); +ParseSystemInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { + const MDRawSystemInfo* sysinfo = range.GetData(0); if (!sysinfo) { fprintf(stderr, "Failed to access MD_SYSTEM_INFO_STREAM\n"); _exit(1); @@ -442,7 +385,8 @@ ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range, #else #error "This code has not been ported to your platform yet" #endif - if (!strstr(full_file.GetString(sysinfo->csd_version_rva).c_str(), "Linux")) { + if (!strstr(full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str(), + "Linux")) { fprintf(stderr, "This minidump was not generated by Linux.\n"); _exit(1); } @@ -478,13 +422,13 @@ ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range, fputs("\n", stderr); } fprintf(stderr, "OS: %s\n", - full_file.GetString(sysinfo->csd_version_rva).c_str()); + full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str()); fputs("\n\n", stderr); } } static void -ParseCPUInfo(CrashedProcess* crashinfo, MMappedRange range) { +ParseCPUInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_CPU_INFO:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -493,7 +437,8 @@ ParseCPUInfo(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseProcessStatus(CrashedProcess* crashinfo, MMappedRange range) { +ParseProcessStatus(CrashedProcess* crashinfo, + const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_PROC_STATUS:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -502,7 +447,7 @@ ParseProcessStatus(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseLSBRelease(CrashedProcess* crashinfo, MMappedRange range) { +ParseLSBRelease(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_LSB_RELEASE:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -511,7 +456,7 @@ ParseLSBRelease(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseMaps(CrashedProcess* crashinfo, MMappedRange range) { +ParseMaps(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_MAPS:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -557,7 +502,7 @@ ParseMaps(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseEnvironment(CrashedProcess* crashinfo, MMappedRange range) { +ParseEnvironment(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_ENVIRON:\n", stderr); char *env = new char[range.length()]; @@ -595,7 +540,7 @@ ParseEnvironment(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseAuxVector(CrashedProcess* crashinfo, MMappedRange range) { +ParseAuxVector(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { // Some versions of Chrome erroneously used the MD_LINUX_AUXV stream value // when dumping /proc/$x/maps if (range.length() > 17) { @@ -616,7 +561,7 @@ ParseAuxVector(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseCmdLine(CrashedProcess* crashinfo, MMappedRange range) { +ParseCmdLine(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { // The command line is supposed to use NUL bytes to separate arguments. // As Chrome rewrites its own command line and (incorrectly) substitutes // spaces, this is often not the case in our minidump files. @@ -664,10 +609,9 @@ ParseCmdLine(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange &full_file) { - const MDRawDebug* debug = - (MDRawDebug*) range.GetObject(0, sizeof(MDRawDebug)); +ParseDSODebugInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { + const MDRawDebug* debug = range.GetData(0); if (!debug) { return; } @@ -694,14 +638,13 @@ ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range, if (debug->map != kInvalidMDRVA) { for (int i = 0; i < debug->dso_count; ++i) { const MDRawLinkMap* link_map = - (MDRawLinkMap*) full_file.GetArrayElement(debug->map, - sizeof(MDRawLinkMap), i); + full_file.GetArrayElement(debug->map, i); if (link_map) { if (verbose) { fprintf(stderr, "#%03d: %p, %p, \"%s\"\n", i, link_map->addr, link_map->ld, - full_file.GetString(link_map->name).c_str()); + full_file.GetAsciiMDString(link_map->name).c_str()); } crashinfo->link_map.push_back(*link_map); } @@ -713,9 +656,9 @@ ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range, } static void -ParseExceptionStream(CrashedProcess* crashinfo, MMappedRange range) { - const MDRawExceptionStream* exp = - (MDRawExceptionStream*) range.GetObject(0, sizeof(MDRawExceptionStream)); +ParseExceptionStream(CrashedProcess* crashinfo, + const MinidumpMemoryRange& range) { + const MDRawExceptionStream* exp = range.GetData(0); crashinfo->crashing_tid = exp->thread_id; crashinfo->fatal_signal = (int) exp->exception_record.exception_code; } @@ -763,18 +706,16 @@ WriteThread(const CrashedProcess::Thread& thread, int fatal_signal) { } static void -ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange &full_file) { +ParseModuleStream(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { if (verbose) { fputs("MD_MODULE_LIST_STREAM:\n", stderr); } - const uint32_t num_mappings = - *(const uint32_t*) range.GetObject(0, sizeof(uint32_t)); + const uint32_t num_mappings = *range.GetData(0); for (unsigned i = 0; i < num_mappings; ++i) { CrashedProcess::Mapping mapping; - const MDRawModule* rawmodule = - (MDRawModule*) range.GetArrayElement(sizeof(uint32_t), - MD_MODULE_SIZE, i); + const MDRawModule* rawmodule = reinterpret_cast( + range.GetArrayElement(sizeof(uint32_t), MD_MODULE_SIZE, i)); mapping.start_address = rawmodule->base_of_image; mapping.end_address = rawmodule->size_of_image + rawmodule->base_of_image; @@ -785,9 +726,8 @@ ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range, crashinfo->mappings[mapping.start_address] = mapping; } - const MDCVInfoPDB70* record = - (const MDCVInfoPDB70*)full_file.GetObject(rawmodule->cv_record.rva, - MDCVInfoPDB70_minsize); + const MDCVInfoPDB70* record = reinterpret_cast( + full_file.GetData(rawmodule->cv_record.rva, MDCVInfoPDB70_minsize)); char guid[40]; sprintf(guid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", record->signature.data1, record->signature.data2, @@ -796,7 +736,8 @@ ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range, record->signature.data4[2], record->signature.data4[3], record->signature.data4[4], record->signature.data4[5], record->signature.data4[6], record->signature.data4[7]); - std::string filename = full_file.GetString(rawmodule->module_name_rva); + std::string filename = + full_file.GetAsciiMDString(rawmodule->module_name_rva); size_t slash = filename.find_last_of('/'); std::string basename = slash == std::string::npos ? filename : filename.substr(slash + 1); @@ -869,7 +810,7 @@ AddDataToMapping(CrashedProcess* crashinfo, const std::string& data, static void AugmentMappings(CrashedProcess* crashinfo, - const MMappedRange &full_file) { + const MinidumpMemoryRange& full_file) { // For each thread, find the memory mapping that matches the thread's stack. // Then adjust the mapping to include the stack dump. for (unsigned i = 0; i < crashinfo->threads.size(); ++i) { @@ -903,7 +844,7 @@ AugmentMappings(CrashedProcess* crashinfo, link_map.l_ld = (ElfW(Dyn)*)iter->ld; link_map.l_prev = prev; prev = (struct link_map*)(start_addr + data.size()); - std::string filename = full_file.GetString(iter->name); + std::string filename = full_file.GetAsciiMDString(iter->name); // Look up signature for this filename. If available, change filename // to point to GUID, instead. @@ -976,10 +917,9 @@ main(int argc, char** argv) { return 1; } - MMappedRange dump(mapped_file.data(), mapped_file.size()); + MinidumpMemoryRange dump(mapped_file.data(), mapped_file.size()); - const MDRawHeader* header = - (const MDRawHeader*) dump.GetObject(0, sizeof(MDRawHeader)); + const MDRawHeader* header = dump.GetData(0); CrashedProcess crashinfo; @@ -988,8 +928,7 @@ main(int argc, char** argv) { bool ok = false; for (unsigned i = 0; i < header->stream_count; ++i) { const MDRawDirectory* dirent = - (const MDRawDirectory*) dump.GetArrayElement( - header->stream_directory_rva, sizeof(MDRawDirectory), i); + dump.GetArrayElement(header->stream_directory_rva, i); switch (dirent->stream_type) { case MD_SYSTEM_INFO_STREAM: ParseSystemInfo(&crashinfo, dump.Subrange(dirent->location), dump); @@ -1006,8 +945,7 @@ main(int argc, char** argv) { for (unsigned i = 0; i < header->stream_count; ++i) { const MDRawDirectory* dirent = - (const MDRawDirectory*) dump.GetArrayElement( - header->stream_directory_rva, sizeof(MDRawDirectory), i); + dump.GetArrayElement(header->stream_directory_rva, i); switch (dirent->stream_type) { case MD_THREAD_LIST_STREAM: ParseThreadList(&crashinfo, dump.Subrange(dirent->location), dump); diff --git a/src/tools/linux/md2core/minidump_memory_range.h b/src/tools/linux/md2core/minidump_memory_range.h new file mode 100644 index 00000000..b0d8255f --- /dev/null +++ b/src/tools/linux/md2core/minidump_memory_range.h @@ -0,0 +1,89 @@ +// 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_memory_range.h: Define the google_breakpad::MinidumpMemoryRange +// class, which adds methods for handling minidump specific data structures +// on top of google_breakpad::MemoryRange. See common/memory_range.h for +// more details on MemoryRange. + +#ifndef TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_ +#define TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_ + +#include + +#include "common/memory_range.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// A derived class of MemoryRange with added methods for handling minidump +// specific data structures. To avoid virtual functions, it is not designed +// to be used polymorphically. +class MinidumpMemoryRange : public MemoryRange { + public: + MinidumpMemoryRange() {} + + MinidumpMemoryRange(const void* data, size_t length) + : MemoryRange(data, length) {} + + // Returns a subrange of |length| bytes at |offset| bytes of this memory + // range, or an empty range if the subrange is out of bounds. + // This methods overrides the base implemementation in order to return + // an instance of MinidumpMemoryRange instead of MemoryRange. + MinidumpMemoryRange Subrange(size_t sub_offset, size_t sub_length) const { + if (Covers(sub_offset, sub_length)) + return MinidumpMemoryRange(data() + sub_offset, sub_length); + return MinidumpMemoryRange(); + } + + // Returns a subrange that covers the offset and length specified by + // |location|, or an empty range if the subrange is out of bounds. + MinidumpMemoryRange Subrange(const MDLocationDescriptor& location) const { + return MinidumpMemoryRange::Subrange(location.rva, location.data_size); + } + + // Gets a STL string from a MDString at |sub_offset| bytes of this memory + // range. This method only works correctly for ASCII characters and does + // not convert between UTF-16 and UTF-8. + const std::string GetAsciiMDString(size_t sub_offset) const { + std::string str; + const MDString* md_str = GetData(sub_offset); + if (md_str) { + const u_int16_t* buffer = &md_str->buffer[0]; + for (u_int32_t i = 0; i < md_str->length && buffer[i]; ++i) { + str.push_back(buffer[i]); + } + } + return str; + } +}; + +} // namespace google_breakpad + +#endif // TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_ diff --git a/src/tools/linux/md2core/minidump_memory_range_unittest.cc b/src/tools/linux/md2core/minidump_memory_range_unittest.cc new file mode 100644 index 00000000..bf94ad52 --- /dev/null +++ b/src/tools/linux/md2core/minidump_memory_range_unittest.cc @@ -0,0 +1,258 @@ +// 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_memory_range_unittest.cc: +// Unit tests for google_breakpad::MinidumpMemoryRange. + +#include "breakpad_googletest_includes.h" +#include "tools/linux/md2core/minidump_memory_range.h" + +using google_breakpad::MinidumpMemoryRange; +using testing::Message; + +namespace { + +const u_int32_t kBuffer[10] = { 0 }; +const size_t kBufferSize = sizeof(kBuffer); +const u_int8_t* kBufferPointer = reinterpret_cast(kBuffer); + +// Test vectors for verifying Covers, GetData, and Subrange. +const struct { + bool valid; + size_t offset; + size_t length; +} kSubranges[] = { + { true, 0, 0 }, + { true, 0, 2 }, + { true, 0, kBufferSize }, + { true, 2, 0 }, + { true, 2, 4 }, + { true, 2, kBufferSize - 2 }, + { true, kBufferSize - 1, 1 }, + { false, kBufferSize, 0 }, + { false, kBufferSize, -1 }, + { false, kBufferSize + 1, 0 }, + { false, -1, 2 }, + { false, 1, kBufferSize }, + { false, kBufferSize - 1, 2 }, + { false, 0, -1 }, + { false, 1, -1 }, +}; +const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]); + +// Test vectors for verifying GetArrayElement. +const struct { + size_t offset; + size_t size; + size_t index; + const void* const pointer; +} kElements[] = { + // Valid array elemenets + { 0, 1, 0, kBufferPointer }, + { 0, 1, 1, kBufferPointer + 1 }, + { 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 }, + { 0, 2, 1, kBufferPointer + 2 }, + { 0, 4, 2, kBufferPointer + 8 }, + { 0, 4, 9, kBufferPointer + 36 }, + { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 }, + // Invalid array elemenets + { 0, 1, kBufferSize, NULL }, + { 0, 4, 10, NULL }, + { kBufferSize - 1, 1, 1, NULL }, + { kBufferSize - 1, 2, 0, NULL }, + { kBufferSize, 1, 0, NULL }, +}; +const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); + +} // namespace + +TEST(MinidumpMemoryRangeTest, DefaultConstructor) { + MinidumpMemoryRange range; + EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(0, range.length()); +} + +TEST(MinidumpMemoryRangeTest, ConstructorWithDataAndLength) { + MinidumpMemoryRange range(kBuffer, kBufferSize); + EXPECT_EQ(kBufferPointer, range.data()); + EXPECT_EQ(kBufferSize, range.length()); +} + +TEST(MinidumpMemoryRangeTest, Reset) { + MinidumpMemoryRange range; + range.Reset(); + EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(0, range.length()); + + range.Set(kBuffer, kBufferSize); + EXPECT_EQ(kBufferPointer, range.data()); + EXPECT_EQ(kBufferSize, range.length()); + + range.Reset(); + EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(0, range.length()); +} + +TEST(MinidumpMemoryRangeTest, Set) { + MinidumpMemoryRange range; + range.Set(kBuffer, kBufferSize); + EXPECT_EQ(kBufferPointer, range.data()); + EXPECT_EQ(kBufferSize, range.length()); + + range.Set(NULL, 0); + EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(0, range.length()); +} + +TEST(MinidumpMemoryRangeTest, SubrangeOfEmptyMemoryRange) { + MinidumpMemoryRange range; + MinidumpMemoryRange subrange = range.Subrange(0, 10); + EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(0, subrange.length()); +} + +TEST(MinidumpMemoryRangeTest, SubrangeAndGetData) { + MinidumpMemoryRange range(kBuffer, kBufferSize); + for (size_t i = 0; i < kNumSubranges; ++i) { + bool valid = kSubranges[i].valid; + size_t sub_offset = kSubranges[i].offset; + size_t sub_length = kSubranges[i].length; + SCOPED_TRACE(Message() << "offset=" << sub_offset + << ", length=" << sub_length); + + MinidumpMemoryRange subrange = range.Subrange(sub_offset, sub_length); + if (valid) { + EXPECT_TRUE(range.Covers(sub_offset, sub_length)); + EXPECT_EQ(kBufferPointer + sub_offset, + range.GetData(sub_offset, sub_length)); + EXPECT_EQ(kBufferPointer + sub_offset, subrange.data()); + EXPECT_EQ(sub_length, subrange.length()); + } else { + EXPECT_FALSE(range.Covers(sub_offset, sub_length)); + EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); + EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(0, subrange.length()); + } + } +} + +TEST(MinidumpMemoryRangeTest, SubrangeWithMDLocationDescriptor) { + MinidumpMemoryRange range(kBuffer, kBufferSize); + for (size_t i = 0; i < kNumSubranges; ++i) { + bool valid = kSubranges[i].valid; + size_t sub_offset = kSubranges[i].offset; + size_t sub_length = kSubranges[i].length; + SCOPED_TRACE(Message() << "offset=" << sub_offset + << ", length=" << sub_length); + + MDLocationDescriptor location; + location.rva = sub_offset; + location.data_size = sub_length; + MinidumpMemoryRange subrange = range.Subrange(location); + if (valid) { + EXPECT_TRUE(range.Covers(sub_offset, sub_length)); + EXPECT_EQ(kBufferPointer + sub_offset, + range.GetData(sub_offset, sub_length)); + EXPECT_EQ(kBufferPointer + sub_offset, subrange.data()); + EXPECT_EQ(sub_length, subrange.length()); + } else { + EXPECT_FALSE(range.Covers(sub_offset, sub_length)); + EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); + EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(0, subrange.length()); + } + } +} + +TEST(MinidumpMemoryRangeTest, GetDataWithTemplateType) { + MinidumpMemoryRange range(kBuffer, kBufferSize); + const char* char_pointer = range.GetData(0); + EXPECT_EQ(reinterpret_cast(kBufferPointer), char_pointer); + const int* int_pointer = range.GetData(0); + EXPECT_EQ(reinterpret_cast(kBufferPointer), int_pointer); +} + +TEST(MinidumpMemoryRangeTest, GetArrayElement) { + MinidumpMemoryRange range(kBuffer, kBufferSize); + for (size_t i = 0; i < kNumElements; ++i) { + size_t element_offset = kElements[i].offset; + size_t element_size = kElements[i].size; + unsigned element_index = kElements[i].index; + const void* const element_pointer = kElements[i].pointer; + SCOPED_TRACE(Message() << "offset=" << element_offset + << ", size=" << element_size + << ", index=" << element_index); + EXPECT_EQ(element_pointer, range.GetArrayElement( + element_offset, element_size, element_index)); + } +} + +TEST(MinidumpMemoryRangeTest, GetArrayElmentWithTemplateType) { + MinidumpMemoryRange range(kBuffer, kBufferSize); + const char* char_pointer = range.GetArrayElement(0, 0); + EXPECT_EQ(reinterpret_cast(kBufferPointer), char_pointer); + const int* int_pointer = range.GetArrayElement(0, 0); + EXPECT_EQ(reinterpret_cast(kBufferPointer), int_pointer); +} + +TEST(MinidumpMemoryRangeTest, GetAsciiMDString) { + u_int8_t buffer[100] = { 0 }; + + MDString* md_str = reinterpret_cast(buffer); + md_str->length = 4; + md_str->buffer[0] = 'T'; + md_str->buffer[1] = 'e'; + md_str->buffer[2] = 's'; + md_str->buffer[3] = 't'; + md_str->buffer[4] = '\0'; + + size_t str2_offset = + sizeof(MDString) + (md_str->length + 1) * sizeof(u_int16_t); + + md_str = reinterpret_cast(buffer + str2_offset); + md_str->length = 9; // Test length larger than actual string + md_str->buffer[0] = 'S'; + md_str->buffer[1] = 't'; + md_str->buffer[2] = 'r'; + md_str->buffer[3] = 'i'; + md_str->buffer[4] = 'n'; + md_str->buffer[5] = 'g'; + md_str->buffer[6] = '\0'; + md_str->buffer[7] = '1'; + md_str->buffer[8] = '2'; + + MinidumpMemoryRange range(buffer, sizeof(buffer)); + EXPECT_EQ("Test", range.GetAsciiMDString(0)); + EXPECT_EQ("String", range.GetAsciiMDString(str2_offset)); + + // Test out-of-bounds cases. + EXPECT_EQ("", range.GetAsciiMDString( + sizeof(buffer) - sizeof(MDString) + 1)); + EXPECT_EQ("", range.GetAsciiMDString(sizeof(buffer))); +}