FastSourceLineResolver implementation for optimization purpose.

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@719 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
SiyangXie@gmail.com 2010-10-21 17:13:01 +00:00
parent 43378265bf
commit 41f998fe5a
18 changed files with 23790 additions and 8 deletions

View file

@ -85,6 +85,7 @@ src_libbreakpad_a_SOURCES = \
src/google_breakpad/processor/code_module.h \
src/google_breakpad/processor/code_modules.h \
src/google_breakpad/processor/exploitability.h \
src/google_breakpad/processor/fast_source_line_resolver.h \
src/google_breakpad/processor/memory_region.h \
src/google_breakpad/processor/minidump.h \
src/google_breakpad/processor/minidump_processor.h \
@ -116,6 +117,8 @@ src_libbreakpad_a_SOURCES = \
src/processor/exploitability.cc \
src/processor/exploitability_win.h \
src/processor/exploitability_win.cc \
src/processor/fast_source_line_resolver_types.h \
src/processor/fast_source_line_resolver.cc \
src/processor/linked_ptr.h \
src/processor/logging.h \
src/processor/logging.cc \
@ -123,6 +126,9 @@ src_libbreakpad_a_SOURCES = \
src/processor/map_serializers.h \
src/processor/minidump.cc \
src/processor/minidump_processor.cc \
src/processor/module_comparer.cc \
src/processor/module_comparer.h \
src/processor/module_factory.h \
src/processor/network_interface.h \
src/processor/network_source_line_resolver.cc \
src/processor/network_source_line_server.cc \
@ -221,6 +227,7 @@ check_PROGRAMS += \
src/processor/contained_range_map_unittest \
src/processor/disassembler_x86_unittest \
src/processor/exploitability_unittest \
src/processor/fast_source_line_resolver_unittest \
src/processor/map_serializers_unittest \
src/processor/minidump_processor_unittest \
src/processor/minidump_unittest \
@ -414,6 +421,27 @@ src_processor_disassembler_x86_unittest_LDADD = \
src/processor/disassembler_x86.o \
src/third_party/libdisasm/libdisasm.a
src_processor_fast_source_line_resolver_unittest_SOURCES = \
src/processor/fast_source_line_resolver_unittest.cc \
src/testing/gtest/src/gtest-all.cc \
src/testing/src/gmock-all.cc
src_processor_fast_source_line_resolver_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
src_processor_fast_source_line_resolver_unittest_LDADD = \
src/processor/fast_source_line_resolver.o \
src/processor/basic_source_line_resolver.o \
src/processor/cfi_frame_info.o \
src/processor/module_comparer.o \
src/processor/module_serializer.o \
src/processor/pathname_stripper.o \
src/processor/logging.o \
src/processor/source_line_resolver_base.o \
src/processor/tokenize.o
src_processor_map_serializers_unittest_SOURCES = \
src/processor/map_serializers_unittest.cc \
src/testing/gtest/src/gtest-all.cc \

View file

@ -88,6 +88,7 @@ check_PROGRAMS = $(am__EXEEXT_3) $(am__EXEEXT_4) $(am__EXEEXT_5)
@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_unittest \
@ -191,6 +192,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
src/google_breakpad/processor/code_module.h \
src/google_breakpad/processor/code_modules.h \
src/google_breakpad/processor/exploitability.h \
src/google_breakpad/processor/fast_source_line_resolver.h \
src/google_breakpad/processor/memory_region.h \
src/google_breakpad/processor/minidump.h \
src/google_breakpad/processor/minidump_processor.h \
@ -218,11 +220,15 @@ am__src_libbreakpad_a_SOURCES_DIST = \
src/processor/disassembler_x86.cc \
src/processor/exploitability.cc \
src/processor/exploitability_win.h \
src/processor/exploitability_win.cc src/processor/linked_ptr.h \
src/processor/logging.h src/processor/logging.cc \
src/processor/map_serializers-inl.h \
src/processor/exploitability_win.cc \
src/processor/fast_source_line_resolver_types.h \
src/processor/fast_source_line_resolver.cc \
src/processor/linked_ptr.h src/processor/logging.h \
src/processor/logging.cc src/processor/map_serializers-inl.h \
src/processor/map_serializers.h src/processor/minidump.cc \
src/processor/minidump_processor.cc \
src/processor/module_comparer.cc \
src/processor/module_comparer.h src/processor/module_factory.h \
src/processor/network_interface.h \
src/processor/network_source_line_resolver.cc \
src/processor/network_source_line_server.cc \
@ -270,9 +276,11 @@ am__src_libbreakpad_a_SOURCES_DIST = \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.$(OBJEXT) \
@ -346,6 +354,7 @@ src_third_party_libdisasm_libdisasm_a_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_unittest$(EXEEXT) \
@ -520,6 +529,23 @@ src_processor_exploitability_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
am__src_processor_fast_source_line_resolver_unittest_SOURCES_DIST = \
src/processor/fast_source_line_resolver_unittest.cc \
src/testing/gtest/src/gtest-all.cc \
src/testing/src/gmock-all.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_fast_source_line_resolver_unittest_OBJECTS = src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.$(OBJEXT)
src_processor_fast_source_line_resolver_unittest_OBJECTS = $(am_src_processor_fast_source_line_resolver_unittest_OBJECTS)
@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_DEPENDENCIES = src/processor/fast_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o
am__src_processor_map_serializers_unittest_SOURCES_DIST = \
src/processor/map_serializers_unittest.cc \
src/testing/gtest/src/gtest-all.cc \
@ -889,6 +915,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \
$(src_processor_contained_range_map_unittest_SOURCES) \
$(src_processor_disassembler_x86_unittest_SOURCES) \
$(src_processor_exploitability_unittest_SOURCES) \
$(src_processor_fast_source_line_resolver_unittest_SOURCES) \
$(src_processor_map_serializers_unittest_SOURCES) \
$(src_processor_minidump_dump_SOURCES) \
$(src_processor_minidump_processor_unittest_SOURCES) \
@ -924,6 +951,7 @@ DIST_SOURCES = \
$(am__src_processor_contained_range_map_unittest_SOURCES_DIST) \
$(am__src_processor_disassembler_x86_unittest_SOURCES_DIST) \
$(am__src_processor_exploitability_unittest_SOURCES_DIST) \
$(am__src_processor_fast_source_line_resolver_unittest_SOURCES_DIST) \
$(am__src_processor_map_serializers_unittest_SOURCES_DIST) \
$(am__src_processor_minidump_dump_SOURCES_DIST) \
$(am__src_processor_minidump_processor_unittest_SOURCES_DIST) \
@ -1101,6 +1129,7 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/code_module.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/code_modules.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/exploitability.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/fast_source_line_resolver.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/memory_region.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump_processor.h \
@ -1132,6 +1161,8 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_types.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/linked_ptr.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.cc \
@ -1139,6 +1170,9 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_factory.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/network_interface.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.cc \
@ -1381,6 +1415,29 @@ TESTS_ENVIRONMENT =
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_unittest.cc \
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/gtest-all.cc \
@DISABLE_PROCESSOR_FALSE@ src/testing/src/gmock-all.cc
@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_CPPFLAGS = \
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing
@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_LDADD = \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o
@DISABLE_PROCESSOR_FALSE@src_processor_map_serializers_unittest_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers_unittest.cc \
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/gtest-all.cc \
@ -2095,6 +2152,9 @@ src/processor/exploitability.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/exploitability_win.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/fast_source_line_resolver.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/logging.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/minidump.$(OBJEXT): src/processor/$(am__dirstamp) \
@ -2102,6 +2162,9 @@ src/processor/minidump.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/minidump_processor.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/module_comparer.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/network_source_line_resolver.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
@ -2401,6 +2464,18 @@ src/testing/src/src_processor_exploitability_unittest-gmock-all.$(OBJEXT): \
src/processor/exploitability_unittest$(EXEEXT): $(src_processor_exploitability_unittest_OBJECTS) $(src_processor_exploitability_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/exploitability_unittest$(EXEEXT)
$(CXXLINK) $(src_processor_exploitability_unittest_OBJECTS) $(src_processor_exploitability_unittest_LDADD) $(LIBS)
src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.$(OBJEXT): \
src/testing/gtest/src/$(am__dirstamp) \
src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.$(OBJEXT): \
src/testing/src/$(am__dirstamp) \
src/testing/src/$(DEPDIR)/$(am__dirstamp)
src/processor/fast_source_line_resolver_unittest$(EXEEXT): $(src_processor_fast_source_line_resolver_unittest_OBJECTS) $(src_processor_fast_source_line_resolver_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/fast_source_line_resolver_unittest$(EXEEXT)
$(CXXLINK) $(src_processor_fast_source_line_resolver_unittest_OBJECTS) $(src_processor_fast_source_line_resolver_unittest_LDADD) $(LIBS)
src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
@ -2682,11 +2757,13 @@ mostlyclean-compile:
-rm -f src/processor/disassembler_x86.$(OBJEXT)
-rm -f src/processor/exploitability.$(OBJEXT)
-rm -f src/processor/exploitability_win.$(OBJEXT)
-rm -f src/processor/fast_source_line_resolver.$(OBJEXT)
-rm -f src/processor/logging.$(OBJEXT)
-rm -f src/processor/minidump.$(OBJEXT)
-rm -f src/processor/minidump_dump.$(OBJEXT)
-rm -f src/processor/minidump_processor.$(OBJEXT)
-rm -f src/processor/minidump_stackwalk.$(OBJEXT)
-rm -f src/processor/module_comparer.$(OBJEXT)
-rm -f src/processor/network_source_line_resolver.$(OBJEXT)
-rm -f src/processor/network_source_line_server.$(OBJEXT)
-rm -f src/processor/pathname_stripper.$(OBJEXT)
@ -2706,6 +2783,7 @@ mostlyclean-compile:
-rm -f src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.$(OBJEXT)
-rm -f src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.$(OBJEXT)
-rm -f src/processor/src_processor_exploitability_unittest-exploitability_unittest.$(OBJEXT)
-rm -f src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.$(OBJEXT)
-rm -f src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.$(OBJEXT)
-rm -f src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT)
-rm -f src/processor/src_processor_minidump_unittest-minidump_unittest.$(OBJEXT)
@ -2743,6 +2821,7 @@ mostlyclean-compile:
-rm -f src/testing/gtest/src/src_processor_disassembler_x86_unittest-gtest_main.$(OBJEXT)
-rm -f src/testing/gtest/src/src_processor_exploitability_unittest-gtest-all.$(OBJEXT)
-rm -f src/testing/gtest/src/src_processor_exploitability_unittest-gtest_main.$(OBJEXT)
-rm -f src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.$(OBJEXT)
-rm -f src/testing/gtest/src/src_processor_map_serializers_unittest-gtest-all.$(OBJEXT)
-rm -f src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT)
-rm -f src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.$(OBJEXT)
@ -2769,6 +2848,7 @@ mostlyclean-compile:
-rm -f src/testing/src/src_processor_cfi_frame_info_unittest-gmock-all.$(OBJEXT)
-rm -f src/testing/src/src_processor_disassembler_x86_unittest-gmock-all.$(OBJEXT)
-rm -f src/testing/src/src_processor_exploitability_unittest-gmock-all.$(OBJEXT)
-rm -f src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.$(OBJEXT)
-rm -f src/testing/src/src_processor_map_serializers_unittest-gmock-all.$(OBJEXT)
-rm -f src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT)
-rm -f src/testing/src/src_processor_minidump_unittest-gmock-all.$(OBJEXT)
@ -2835,11 +2915,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/disassembler_x86.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/exploitability.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/exploitability_win.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/fast_source_line_resolver.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_stackwalk.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/module_comparer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/network_source_line_resolver.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/network_source_line_server.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper.Po@am__quote@
@ -2859,6 +2941,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Po@am__quote@
@ -2896,6 +2979,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_disassembler_x86_unittest-gtest_main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_exploitability_unittest-gtest-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_exploitability_unittest-gtest_main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gtest-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_map_serializers_unittest-gtest-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest-all.Po@am__quote@
@ -2922,6 +3006,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_cfi_frame_info_unittest-gmock-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_disassembler_x86_unittest-gmock-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_exploitability_unittest-gmock-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gmock-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_map_serializers_unittest-gmock-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_minidump_unittest-gmock-all.Po@am__quote@
@ -3501,6 +3586,48 @@ src/testing/src/src_processor_exploitability_unittest-gmock-all.obj: src/testing
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_exploitability_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_exploitability_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/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o: src/processor/fast_source_line_resolver_unittest.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o `test -f 'src/processor/fast_source_line_resolver_unittest.cc' || echo '$(srcdir)/'`src/processor/fast_source_line_resolver_unittest.cc
@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/fast_source_line_resolver_unittest.cc' object='src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o `test -f 'src/processor/fast_source_line_resolver_unittest.cc' || echo '$(srcdir)/'`src/processor/fast_source_line_resolver_unittest.cc
src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj: src/processor/fast_source_line_resolver_unittest.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj `if test -f 'src/processor/fast_source_line_resolver_unittest.cc'; then $(CYGPATH_W) 'src/processor/fast_source_line_resolver_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/fast_source_line_resolver_unittest.cc'; fi`
@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/fast_source_line_resolver_unittest.cc' object='src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj `if test -f 'src/processor/fast_source_line_resolver_unittest.cc'; then $(CYGPATH_W) 'src/processor/fast_source_line_resolver_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/fast_source_line_resolver_unittest.cc'; fi`
src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gtest-all.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest-gtest-all.obj: src/testing/gtest/src/gtest-all.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gtest-all.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_fast_source_line_resolver_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/src/src_processor_fast_source_line_resolver_unittest-gmock-all.o: src/testing/src/gmock-all.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gmock-all.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.obj: src/testing/src/gmock-all.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-gmock-all.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_fast_source_line_resolver_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_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_fast_source_line_resolver_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/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o: src/processor/map_serializers_unittest.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_map_serializers_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Tpo -c -o src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o `test -f 'src/processor/map_serializers_unittest.cc' || echo '$(srcdir)/'`src/processor/map_serializers_unittest.cc
@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Tpo src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Po

View file

@ -64,6 +64,8 @@ class BasicSourceLineResolver : public SourceLineResolverBase {
private:
// friend declarations:
friend class BasicModuleFactory;
friend class ModuleComparer;
friend class ModuleSerializer;
template<class> friend class SimpleSerializer;
// Function derives from SourceLineResolverBase::Function.
@ -71,7 +73,9 @@ class BasicSourceLineResolver : public SourceLineResolverBase {
// Module implements SourceLineResolverBase::Module interface.
class Module;
// Helper method.
// Helper methods to manage C-String format symbol data.
// See "google_breakpad/processor/source_line_resolver_base.h" for more
// comments about these helper methods.
virtual void DeleteDataAfterLoad(char *symbol_data);
// No-op helper methods.
virtual void DeleteDataUnload(const CodeModule *module) { }

View file

@ -0,0 +1,107 @@
// Copyright (c) 2010 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.
//
// fast_source_line_resolver.h: FastSourceLineResolver is derived from
// SourceLineResolverBase, and is a concrete implementation of
// SourceLineResolverInterface.
//
// FastSourceLineResolver is a sibling class of BasicSourceLineResolver. The
// difference is FastSourceLineResolver loads a serialized memory chunk of data
// which can be used directly a Module without parsing or copying of underlying
// data. Therefore loading a symbol in FastSourceLineResolver is much faster
// and more memory-efficient than BasicSourceLineResolver.
//
// See "source_line_resolver_base.h" and
// "google_breakpad/source_line_resolver_interface.h" for more reference.
//
// Author: Siyang Xie (lambxsy@google.com)
#ifndef GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
#define GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
#include <map>
#include <string>
#include "google_breakpad/processor/source_line_resolver_base.h"
namespace google_breakpad {
using std::map;
class FastSourceLineResolver : public SourceLineResolverBase {
public:
FastSourceLineResolver();
virtual ~FastSourceLineResolver() { }
using SourceLineResolverBase::FillSourceLineInfo;
using SourceLineResolverBase::FindCFIFrameInfo;
using SourceLineResolverBase::FindWindowsFrameInfo;
using SourceLineResolverBase::HasModule;
using SourceLineResolverBase::LoadModule;
using SourceLineResolverBase::LoadModuleUsingMapBuffer;
using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
using SourceLineResolverBase::UnloadModule;
private:
// Friend declarations.
friend class ModuleComparer;
friend class ModuleSerializer;
friend class FastModuleFactory;
// Nested types that will derive from corresponding nested types defined in
// SourceLineResolverBase.
struct Line;
struct Function;
struct PublicSymbol;
class Module;
// Deserialize raw memory data to construct a WindowsFrameInfo object.
static WindowsFrameInfo CopyWFI(const char *raw_memory);
// Helper methods to manage C-String format symbol data.
// See "google_breakpad/processor/source_line_resolver_base.h" for more
// comments about these helper methods.
virtual void StoreDataBeforeLoad(const CodeModule *module, char *symbol_data);
virtual void DeleteDataUnload(const CodeModule *module);
virtual void ClearLocalMemory();
// No-op helper method.
virtual void DeleteDataAfterLoad(char *symbol_data) { }
// Store memory data allocated in LoadModule and LoadModuleUsingMapBuffer.
typedef std::map<string, char*, CompareString> MemoryMap;
MemoryMap memory_chunks_;
// Disallow unwanted copy ctor and assignment operator
FastSourceLineResolver(const FastSourceLineResolver&);
void operator=(const FastSourceLineResolver&);
};
} // namespace google_breakpad
#endif // GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__

View file

@ -80,9 +80,26 @@ class SourceLineResolverBase : public SourceLineResolverInterface {
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame);
// Helper methods to manage C-String format symbol data.
// These methods are defined as no-op by default.
//
// StoreDataBeforeLoad() will be called in LoadModule() and
// LoadModuleUsingMapBuffer() to let subclass decide whether or how to store
// the dynamicly allocated memory data, before passing the data to
// LoadModuleUsingMemoryBuffer() which actually loads the module.
virtual void StoreDataBeforeLoad(const CodeModule *module, char *symbol_data);
// DeleteDataAfterLoad() will be called at the end of
// LoadModuleUsingMemoryBuffer() to let subclass decide whether to delete the
// allocated memory data or not (which depends on whether the subclass has
// ownership of the data or not).
virtual void DeleteDataAfterLoad(char *symbol_data);
// DeleteDataUnload() will be called in UnloadModule() to let subclass clean
// up dynamicly allocated data associated with the module, if there is any.
virtual void DeleteDataUnload(const CodeModule *module);
// ClearLocalMemory() will be called in destructor to let subclass clean up
// all local memory data it owns, if there is any.
virtual void ClearLocalMemory();
// Nested structs and classes.

View file

@ -69,6 +69,7 @@ class AddressMap {
private:
friend class AddressMapSerializer<AddressType, EntryType>;
friend class ModuleComparer;
// Convenience types.
typedef std::map<AddressType, EntryType> AddressToEntryMap;

View file

@ -100,6 +100,8 @@ class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module {
private:
// Friend declarations.
friend class BasicSourceLineResolver;
friend class ModuleComparer;
friend class ModuleSerializer;
typedef std::map<int, string> FileMap;

View file

@ -106,6 +106,7 @@ class ContainedRangeMap {
private:
friend class ContainedRangeMapSerializer<AddressType, EntryType>;
friend class ModuleComparer;
// AddressToRangeMap stores pointers. This makes reparenting simpler in
// StoreRange, because it doesn't need to copy entire objects.

View file

@ -0,0 +1,278 @@
// Copyright (c) 2010 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.
//
// fast_source_line_resolver.cc: FastSourceLineResolver is a concrete class that
// implements SourceLineResolverInterface. Both FastSourceLineResolver and
// BasicSourceLineResolver inherit from SourceLineResolverBase class to reduce
// code redundancy.
//
// See fast_source_line_resolver.h and fast_source_line_resolver_types.h
// for more documentation.
//
// Author: Siyang Xie (lambxsy@google.com)
#include "google_breakpad/processor/fast_source_line_resolver.h"
#include "processor/fast_source_line_resolver_types.h"
#include <map>
#include <utility>
#include "processor/module_factory.h"
#include "processor/scoped_ptr.h"
using std::map;
using std::make_pair;
namespace google_breakpad {
FastSourceLineResolver::FastSourceLineResolver()
: SourceLineResolverBase(new FastModuleFactory) { }
void FastSourceLineResolver::ClearLocalMemory() {
for (MemoryMap::iterator it = memory_chunks_.begin();
it != memory_chunks_.end();
++it) {
delete it->second;
}
}
void FastSourceLineResolver::DeleteDataUnload(const CodeModule *module) {
if (module) {
MemoryMap::iterator iter = memory_chunks_.find(module->code_file());
if (iter != memory_chunks_.end()) {
delete iter->second;
}
}
}
void FastSourceLineResolver::StoreDataBeforeLoad(const CodeModule *module,
char *symbol_data) {
memory_chunks_.insert(make_pair(module->code_file(), symbol_data));
}
void FastSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
// First, look for a FUNC record that covers address. Use
// RetrieveNearestRange instead of RetrieveRange so that, if there
// is no such function, we can use the next function to bound the
// extent of the PUBLIC symbol we find, below. This does mean we
// need to check that address indeed falls within the function we
// find; do the range comparison in an overflow-friendly way.
scoped_ptr<Function> func(new Function);
const Function* func_ptr = 0;
scoped_ptr<PublicSymbol> public_symbol(new PublicSymbol);
const PublicSymbol* public_symbol_ptr = 0;
MemAddr function_base;
MemAddr function_size;
MemAddr public_address;
if (functions_.RetrieveNearestRange(address, func_ptr,
&function_base, &function_size) &&
address >= function_base && address - function_base < function_size) {
func.get()->CopyFrom(func_ptr);
frame->function_name = func->name;
frame->function_base = frame->module->base_address() + function_base;
scoped_ptr<Line> line(new Line);
const Line* line_ptr = 0;
MemAddr line_base;
if (func->lines.RetrieveRange(address, line_ptr, &line_base, NULL)) {
line.get()->CopyFrom(line_ptr);
FileMap::iterator it = files_.find(line->source_file_id);
if (it != files_.end()) {
frame->source_file_name =
files_.find(line->source_file_id).GetValuePtr();
}
frame->source_line = line->line;
frame->source_line_base = frame->module->base_address() + line_base;
}
} else if (public_symbols_.Retrieve(address,
public_symbol_ptr, &public_address) &&
(!func_ptr || public_address > function_base)) {
public_symbol.get()->CopyFrom(public_symbol_ptr);
frame->function_name = public_symbol->name;
frame->function_base = frame->module->base_address() + public_address;
}
}
// WFI: WindowsFrameInfo.
// Returns a WFI object reading from a raw memory chunk of data
WindowsFrameInfo FastSourceLineResolver::CopyWFI(const char *raw) {
// The first 4Bytes of int data are unused.
// They corresponds to "int valid;" data member of WFI.
const u_int32_t *para_uint32 = reinterpret_cast<const u_int32_t*>(
raw + sizeof(int32_t));
u_int32_t prolog_size = para_uint32[0];;
u_int32_t epilog_size = para_uint32[1];
u_int32_t parameter_size = para_uint32[2];
u_int32_t saved_register_size = para_uint32[3];
u_int32_t local_size = para_uint32[4];
u_int32_t max_stack_size = para_uint32[5];
const char *boolean = reinterpret_cast<const char*>(para_uint32 + 6);
bool allocates_base_pointer = (*boolean != 0);
std::string program_string = boolean + 1;
return WindowsFrameInfo(prolog_size,
epilog_size,
parameter_size,
saved_register_size,
local_size,
max_stack_size,
allocates_base_pointer,
program_string);
}
// Loads a map from the given buffer in char* type.
// Does NOT take ownership of mem_buffer.
// In addition, treat mem_buffer as const char*.
bool FastSourceLineResolver::Module::LoadMapFromMemory(char *mem_buffer) {
if (!mem_buffer) return false;
const u_int32_t *map_sizes = reinterpret_cast<const u_int32_t*>(mem_buffer);
unsigned int header_size = kNumberMaps_ * sizeof(unsigned int);
// offsets[]: an array of offset addresses (with respect to mem_buffer),
// for each "Static***Map" component of Module.
// "Static***Map": static version of std::map or map wrapper, i.e., StaticMap,
// StaticAddressMap, StaticContainedRangeMap, and StaticRangeMap.
unsigned int offsets[kNumberMaps_];
offsets[0] = header_size;
for (int i = 1; i < kNumberMaps_; ++i) {
offsets[i] = offsets[i - 1] + map_sizes[i - 1];
}
// Use pointers to construct Static*Map data members in Module:
int map_id = 0;
files_ = StaticMap<int, char>(mem_buffer + offsets[map_id++]);
functions_ =
StaticRangeMap<MemAddr, Function>(mem_buffer + offsets[map_id++]);
public_symbols_ =
StaticAddressMap<MemAddr, PublicSymbol>(mem_buffer + offsets[map_id++]);
for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i)
windows_frame_info_[i] =
StaticContainedRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
cfi_initial_rules_ =
StaticRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
cfi_delta_rules_ = StaticMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
return true;
}
WindowsFrameInfo *FastSourceLineResolver::Module::FindWindowsFrameInfo(
const StackFrame *frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo());
// We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and
// WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order.
// WindowsFrameInfo::STACK_INFO_FRAME_DATA is the newer type that
// includes its own program string.
// WindowsFrameInfo::STACK_INFO_FPO is the older type
// corresponding to the FPO_DATA struct. See stackwalker_x86.cc.
const char* frame_info_ptr;
if ((windows_frame_info_[WindowsFrameInfo::STACK_INFO_FRAME_DATA]
.RetrieveRange(address, frame_info_ptr))
|| (windows_frame_info_[WindowsFrameInfo::STACK_INFO_FPO]
.RetrieveRange(address, frame_info_ptr))) {
result->CopyFrom(CopyWFI(frame_info_ptr));
return result.release();
}
// Even without a relevant STACK line, many functions contain
// information about how much space their parameters consume on the
// stack. Use RetrieveNearestRange instead of RetrieveRange, so that
// we can use the function to bound the extent of the PUBLIC symbol,
// below. However, this does mean we need to check that ADDRESS
// falls within the retrieved function's range; do the range
// comparison in an overflow-friendly way.
scoped_ptr<Function> function(new Function);
const Function* function_ptr = 0;
MemAddr function_base, function_size;
if (functions_.RetrieveNearestRange(address, function_ptr,
&function_base, &function_size) &&
address >= function_base && address - function_base < function_size) {
function.get()->CopyFrom(function_ptr);
result->parameter_size = function->parameter_size;
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
return result.release();
}
// PUBLIC symbols might have a parameter size. Use the function we
// found above to limit the range the public symbol covers.
scoped_ptr<PublicSymbol> public_symbol(new PublicSymbol);
const PublicSymbol* public_symbol_ptr = 0;
MemAddr public_address;
if (public_symbols_.Retrieve(address, public_symbol_ptr, &public_address) &&
(!function_ptr || public_address > function_base)) {
public_symbol.get()->CopyFrom(public_symbol_ptr);
result->parameter_size = public_symbol->parameter_size;
}
return NULL;
}
CFIFrameInfo *FastSourceLineResolver::Module::FindCFIFrameInfo(
const StackFrame *frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
MemAddr initial_base, initial_size;
const char* initial_rules = NULL;
// Find the initial rule whose range covers this address. That
// provides an initial set of register recovery rules. Then, walk
// forward from the initial rule's starting address to frame's
// instruction address, applying delta rules.
if (!cfi_initial_rules_.RetrieveRange(address, initial_rules,
&initial_base, &initial_size)) {
return NULL;
}
// Create a frame info structure, and populate it with the rules from
// the STACK CFI INIT record.
scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo());
if (!ParseCFIRuleSet(initial_rules, rules.get()))
return NULL;
// Find the first delta rule that falls within the initial rule's range.
StaticMap<MemAddr, char>::iterator delta =
cfi_delta_rules_.lower_bound(initial_base);
// Apply delta rules up to and including the frame's address.
while (delta != cfi_delta_rules_.end() && delta.GetKey() <= address) {
ParseCFIRuleSet(delta.GetValuePtr(), rules.get());
delta++;
}
return rules.release();
}
} // namespace google_breakpad

View file

@ -0,0 +1,179 @@
// Copyright (c) 2010 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.
//
// fast_source_line_resolver_types.h: definition of nested classes/structs in
// FastSourceLineResolver. It moves the definitions out of
// fast_source_line_resolver.cc, so that other classes could have access
// to these private nested types without including fast_source_line_resolver.cc
//
// Author: lambxsy@google.com (Siyang Xie)
#ifndef PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
#define PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
#include "google_breakpad/processor/fast_source_line_resolver.h"
#include "processor/source_line_resolver_base_types.h"
#include <map>
#include <string>
#include "google_breakpad/processor/stack_frame.h"
#include "processor/cfi_frame_info.h"
#include "processor/static_address_map-inl.h"
#include "processor/static_contained_range_map-inl.h"
#include "processor/static_map.h"
#include "processor/static_range_map-inl.h"
#include "processor/windows_frame_info.h"
namespace google_breakpad {
struct FastSourceLineResolver::Line : public SourceLineResolverBase::Line {
void CopyFrom(const Line *line_ptr) {
const char *raw = reinterpret_cast<const char*>(line_ptr);
CopyFrom(raw);
}
// De-serialize the memory data of a Line.
void CopyFrom(const char *raw) {
address = *(reinterpret_cast<const MemAddr*>(raw));
size = *(reinterpret_cast<const MemAddr*>(raw + sizeof(address)));
source_file_id = *(reinterpret_cast<const int32_t *>(
raw + 2 * sizeof(address)));
line = *(reinterpret_cast<const int32_t*>(
raw + 2 * sizeof(address) + sizeof(source_file_id)));
}
};
struct FastSourceLineResolver::Function :
public SourceLineResolverBase::Function {
void CopyFrom(const Function *func_ptr) {
const char *raw = reinterpret_cast<const char*>(func_ptr);
CopyFrom(raw);
}
// De-serialize the memory data of a Function.
void CopyFrom(const char *raw) {
size_t name_size = strlen(raw) + 1;
name = raw;
address = *(reinterpret_cast<const MemAddr*>(raw + name_size));
size = *(reinterpret_cast<const MemAddr*>(
raw + name_size + sizeof(MemAddr)));
parameter_size = *(reinterpret_cast<const int32_t*>(
raw + name_size + 2 * sizeof(MemAddr)));
lines = StaticRangeMap<MemAddr, Line>(
raw + name_size + 2 * sizeof(MemAddr) + sizeof(int32_t));
}
StaticRangeMap<MemAddr, Line> lines;
};
struct FastSourceLineResolver::PublicSymbol :
public SourceLineResolverBase::PublicSymbol {
void CopyFrom(const PublicSymbol *public_symbol_ptr) {
const char *raw = reinterpret_cast<const char*>(public_symbol_ptr);
CopyFrom(raw);
}
// De-serialize the memory data of a PublicSymbol.
void CopyFrom(const char *raw) {
size_t name_size = strlen(raw) + 1;
name = raw;
address = *(reinterpret_cast<const MemAddr*>(raw + name_size));
parameter_size = *(reinterpret_cast<const int32_t*>(
raw + name_size + sizeof(MemAddr)));
}
};
class FastSourceLineResolver::Module: public SourceLineResolverBase::Module {
public:
explicit Module(const string &name) : name_(name) { }
virtual ~Module() { }
// Looks up the given relative address, and fills the StackFrame struct
// with the result.
virtual void LookupAddress(StackFrame *frame) const;
// Loads a map from the given buffer in char* type.
virtual bool LoadMapFromMemory(char *memory_buffer);
// If Windows stack walking information is available covering ADDRESS,
// return a WindowsFrameInfo structure describing it. If the information
// is not available, returns NULL. A NULL return value does not indicate
// an error. The caller takes ownership of any returned WindowsFrameInfo
// object.
virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const;
// If CFI stack walking information is available covering ADDRESS,
// return a CFIFrameInfo structure describing it. If the information
// is not available, return NULL. The caller takes ownership of any
// returned CFIFrameInfo object.
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const;
private:
friend class FastSourceLineResolver;
friend class ModuleComparer;
typedef StaticMap<int, char> FileMap;
// Number of serialized map components of Module.
static const int kNumberMaps_ = 5 + WindowsFrameInfo::STACK_INFO_LAST;
string name_;
StaticMap<int, char> files_;
StaticRangeMap<MemAddr, Function> functions_;
StaticAddressMap<MemAddr, PublicSymbol> public_symbols_;
// Each element in the array is a ContainedRangeMap for a type
// listed in WindowsFrameInfoTypes. These are split by type because
// there may be overlaps between maps of different types, but some
// information is only available as certain types.
StaticContainedRangeMap<MemAddr, char>
windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST];
// DWARF CFI stack walking data. The Module stores the initial rule sets
// and rule deltas as strings, just as they appear in the symbol file:
// although the file may contain hundreds of thousands of STACK CFI
// records, walking a stack will only ever use a few of them, so it's
// best to delay parsing a record until it's actually needed.
//
// STACK CFI INIT records: for each range, an initial set of register
// recovery rules. The RangeMap's itself gives the starting and ending
// addresses.
StaticRangeMap<MemAddr, char> cfi_initial_rules_;
// STACK CFI records: at a given address, the changes to the register
// recovery rules that take effect at that address. The map key is the
// starting address; the ending address is the key of the next entry in
// this map, or the end of the range as given by the cfi_initial_rules_
// entry (which FindCFIFrameInfo looks up first).
StaticMap<MemAddr, char> cfi_delta_rules_;
};
} // namespace google_breakpad
#endif // PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__

View file

@ -0,0 +1,477 @@
// Copyright (c) 2010 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.
//
// fast_source_line_resolver_unittest.cc: Unit tests for FastSourceLineResolver.
// Two different approaches for testing fast source line resolver:
// First, use the same unit test data for basic source line resolver.
// Second, read data from symbol files, load them as basic modules, and then
// serialize them and load the serialized data as fast modules. Then compare
// modules to assure the fast module contains exactly the same data as
// basic module.
//
// Author: Siyang Xie (lambxsy@google.com)
#include <stdio.h>
#include <sstream>
#include <string>
#include "breakpad_googletest_includes.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/stack_frame.h"
#include "google_breakpad/processor/memory_region.h"
#include "processor/logging.h"
#include "processor/module_serializer.h"
#include "processor/module_comparer.h"
namespace {
using std::string;
using google_breakpad::SourceLineResolverBase;
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::FastSourceLineResolver;
using google_breakpad::ModuleSerializer;
using google_breakpad::ModuleComparer;
using google_breakpad::CFIFrameInfo;
using google_breakpad::CodeModule;
using google_breakpad::MemoryRegion;
using google_breakpad::StackFrame;
using google_breakpad::WindowsFrameInfo;
using google_breakpad::linked_ptr;
using google_breakpad::scoped_ptr;
class TestCodeModule : public CodeModule {
public:
explicit TestCodeModule(string code_file) : code_file_(code_file) {}
virtual ~TestCodeModule() {}
virtual u_int64_t base_address() const { return 0; }
virtual u_int64_t size() const { return 0xb000; }
virtual string code_file() const { return code_file_; }
virtual string code_identifier() const { return ""; }
virtual string debug_file() const { return ""; }
virtual string debug_identifier() const { return ""; }
virtual string version() const { return ""; }
virtual const CodeModule* Copy() const {
return new TestCodeModule(code_file_);
}
private:
string code_file_;
};
// A mock memory region object, for use by the STACK CFI tests.
class MockMemoryRegion: public MemoryRegion {
u_int64_t GetBase() const { return 0x10000; }
u_int32_t GetSize() const { return 0x01000; }
bool GetMemoryAtAddress(u_int64_t address, u_int8_t *value) const {
*value = address & 0xff;
return true;
}
bool GetMemoryAtAddress(u_int64_t address, u_int16_t *value) const {
*value = address & 0xffff;
return true;
}
bool GetMemoryAtAddress(u_int64_t address, u_int32_t *value) const {
switch (address) {
case 0x10008: *value = 0x98ecadc3; break; // saved %ebx
case 0x1000c: *value = 0x878f7524; break; // saved %esi
case 0x10010: *value = 0x6312f9a5; break; // saved %edi
case 0x10014: *value = 0x10038; break; // caller's %ebp
case 0x10018: *value = 0xf6438648; break; // return address
default: *value = 0xdeadbeef; break; // junk
}
return true;
}
bool GetMemoryAtAddress(u_int64_t address, u_int64_t *value) const {
*value = address;
return true;
}
};
// Verify that, for every association in ACTUAL, EXPECTED has the same
// association. (That is, ACTUAL's associations should be a subset of
// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
// ".cfa".
static bool VerifyRegisters(
const char *file, int line,
const CFIFrameInfo::RegisterValueMap<u_int32_t> &expected,
const CFIFrameInfo::RegisterValueMap<u_int32_t> &actual) {
CFIFrameInfo::RegisterValueMap<u_int32_t>::const_iterator a;
a = actual.find(".cfa");
if (a == actual.end())
return false;
a = actual.find(".ra");
if (a == actual.end())
return false;
for (a = actual.begin(); a != actual.end(); a++) {
CFIFrameInfo::RegisterValueMap<u_int32_t>::const_iterator e =
expected.find(a->first);
if (e == expected.end()) {
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
file, line, a->first.c_str(), a->second);
return false;
}
if (e->second != a->second) {
fprintf(stderr,
"%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
file, line, a->first.c_str(), a->second, e->second);
return false;
}
// Don't complain if this doesn't recover all registers. Although
// the DWARF spec says that unmentioned registers are undefined,
// GCC uses omission to mean that they are unchanged.
}
return true;
}
static bool VerifyEmpty(const StackFrame &frame) {
if (frame.function_name.empty() &&
frame.source_file_name.empty() &&
frame.source_line == 0)
return true;
return false;
}
static void ClearSourceLineInfo(StackFrame *frame) {
frame->function_name.clear();
frame->module = NULL;
frame->source_file_name.clear();
frame->source_line = 0;
}
class TestFastSourceLineResolver : public ::testing::Test {
public:
void SetUp() {
testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") +
"/src/processor/testdata";
}
string symbol_file(int file_index) {
std::stringstream ss;
ss << testdata_dir << "/module" << file_index << ".out";
return ss.str();
}
ModuleSerializer serializer;
BasicSourceLineResolver basic_resolver;
FastSourceLineResolver fast_resolver;
ModuleComparer module_comparer;
string testdata_dir;
};
// Test adapted from basic_source_line_resolver_unittest.
TEST_F(TestFastSourceLineResolver, TestLoadAndResolve) {
TestCodeModule module1("module1");
ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1)));
ASSERT_TRUE(basic_resolver.HasModule(&module1));
// Convert module1 to fast_module:
ASSERT_TRUE(serializer.ConvertOneModule(
module1.code_file(), &basic_resolver, &fast_resolver));
ASSERT_TRUE(fast_resolver.HasModule(&module1));
TestCodeModule module2("module2");
ASSERT_TRUE(basic_resolver.LoadModule(&module2, symbol_file(2)));
ASSERT_TRUE(basic_resolver.HasModule(&module2));
// Convert module2 to fast_module:
ASSERT_TRUE(serializer.ConvertOneModule(
module2.code_file(), &basic_resolver, &fast_resolver));
ASSERT_TRUE(fast_resolver.HasModule(&module2));
StackFrame frame;
scoped_ptr<WindowsFrameInfo> windows_frame_info;
scoped_ptr<CFIFrameInfo> cfi_frame_info;
frame.instruction = 0x1000;
frame.module = NULL;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_FALSE(frame.module);
ASSERT_TRUE(frame.function_name.empty());
ASSERT_EQ(frame.function_base, 0);
ASSERT_TRUE(frame.source_file_name.empty());
ASSERT_EQ(frame.source_line, 0);
ASSERT_EQ(frame.source_line_base, 0);
frame.module = &module1;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, "Function1_1");
ASSERT_TRUE(frame.module);
ASSERT_EQ(frame.module->code_file(), "module1");
ASSERT_EQ(frame.function_base, 0x1000);
ASSERT_EQ(frame.source_file_name, "file1_1.cc");
ASSERT_EQ(frame.source_line, 44);
ASSERT_EQ(frame.source_line_base, 0x1000);
windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
ASSERT_TRUE(windows_frame_info.get());
ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
ASSERT_EQ(windows_frame_info->program_string,
"$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =");
ClearSourceLineInfo(&frame);
frame.instruction = 0x800;
frame.module = &module1;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_TRUE(VerifyEmpty(frame));
windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
ASSERT_FALSE(windows_frame_info.get());
frame.instruction = 0x1280;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, "Function1_3");
ASSERT_TRUE(frame.source_file_name.empty());
ASSERT_EQ(frame.source_line, 0);
windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
ASSERT_TRUE(windows_frame_info.get());
ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
ASSERT_TRUE(windows_frame_info->program_string.empty());
frame.instruction = 0x1380;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, "Function1_4");
ASSERT_TRUE(frame.source_file_name.empty());
ASSERT_EQ(frame.source_line, 0);
windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
ASSERT_TRUE(windows_frame_info.get());
ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
ASSERT_FALSE(windows_frame_info->program_string.empty());
frame.instruction = 0x2000;
windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
ASSERT_FALSE(windows_frame_info.get());
// module1 has STACK CFI records covering 3d40..3def;
// module2 has STACK CFI records covering 3df0..3e9f;
// check that FindCFIFrameInfo doesn't claim to find any outside those ranges.
frame.instruction = 0x3d3f;
frame.module = &module1;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_FALSE(cfi_frame_info.get());
frame.instruction = 0x3e9f;
frame.module = &module1;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_FALSE(cfi_frame_info.get());
CFIFrameInfo::RegisterValueMap<u_int32_t> current_registers;
CFIFrameInfo::RegisterValueMap<u_int32_t> caller_registers;
CFIFrameInfo::RegisterValueMap<u_int32_t> expected_caller_registers;
MockMemoryRegion memory;
// Regardless of which instruction evaluation takes place at, it
// should produce the same values for the caller's registers.
expected_caller_registers[".cfa"] = 0x1001c;
expected_caller_registers[".ra"] = 0xf6438648;
expected_caller_registers["$ebp"] = 0x10038;
expected_caller_registers["$ebx"] = 0x98ecadc3;
expected_caller_registers["$esi"] = 0x878f7524;
expected_caller_registers["$edi"] = 0x6312f9a5;
frame.instruction = 0x3d40;
frame.module = &module1;
current_registers.clear();
current_registers["$esp"] = 0x10018;
current_registers["$ebp"] = 0x10038;
current_registers["$ebx"] = 0x98ecadc3;
current_registers["$esi"] = 0x878f7524;
current_registers["$edi"] = 0x6312f9a5;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<u_int32_t>(current_registers, memory,
&caller_registers));
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers));
frame.instruction = 0x3d41;
current_registers["$esp"] = 0x10014;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<u_int32_t>(current_registers, memory,
&caller_registers));
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers));
frame.instruction = 0x3d43;
current_registers["$ebp"] = 0x10014;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<u_int32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d54;
current_registers["$ebx"] = 0x6864f054U;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<u_int32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d5a;
current_registers["$esi"] = 0x6285f79aU;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<u_int32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d84;
current_registers["$edi"] = 0x64061449U;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<u_int32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x2900;
frame.module = &module1;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, string("PublicSymbol"));
frame.instruction = 0x4000;
frame.module = &module1;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, string("LargeFunction"));
frame.instruction = 0x2181;
frame.module = &module2;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, "Function2_2");
ASSERT_EQ(frame.function_base, 0x2170);
ASSERT_TRUE(frame.module);
ASSERT_EQ(frame.module->code_file(), "module2");
ASSERT_EQ(frame.source_file_name, "file2_2.cc");
ASSERT_EQ(frame.source_line, 21);
ASSERT_EQ(frame.source_line_base, 0x2180);
windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
ASSERT_TRUE(windows_frame_info.get());
ASSERT_EQ(windows_frame_info->prolog_size, 1);
frame.instruction = 0x216f;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, "Public2_1");
ClearSourceLineInfo(&frame);
frame.instruction = 0x219f;
frame.module = &module2;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_TRUE(frame.function_name.empty());
frame.instruction = 0x21a0;
frame.module = &module2;
fast_resolver.FillSourceLineInfo(&frame);
ASSERT_EQ(frame.function_name, "Public2_2");
}
TEST_F(TestFastSourceLineResolver, TestInvalidLoads) {
TestCodeModule module3("module3");
ASSERT_FALSE(basic_resolver.LoadModule(&module3,
testdata_dir + "/module3_bad.out"));
ASSERT_FALSE(basic_resolver.HasModule(&module3));
// Convert module3 to fast_module:
ASSERT_FALSE(serializer.ConvertOneModule(module3.code_file(),
&basic_resolver,
&fast_resolver));
ASSERT_FALSE(fast_resolver.HasModule(&module3));
TestCodeModule module4("module4");
ASSERT_FALSE(basic_resolver.LoadModule(&module4,
testdata_dir + "/module4_bad.out"));
ASSERT_FALSE(basic_resolver.HasModule(&module4));
// Convert module4 to fast_module:
ASSERT_FALSE(serializer.ConvertOneModule(module4.code_file(),
&basic_resolver,
&fast_resolver));
ASSERT_FALSE(fast_resolver.HasModule(&module4));
TestCodeModule module5("module5");
ASSERT_FALSE(fast_resolver.LoadModule(&module5,
testdata_dir + "/invalid-filename"));
ASSERT_FALSE(fast_resolver.HasModule(&module5));
TestCodeModule invalidmodule("invalid-module");
ASSERT_FALSE(fast_resolver.HasModule(&invalidmodule));
}
TEST_F(TestFastSourceLineResolver, TestUnload) {
TestCodeModule module1("module1");
ASSERT_FALSE(basic_resolver.HasModule(&module1));
ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1)));
ASSERT_TRUE(basic_resolver.HasModule(&module1));
// Convert module1 to fast_module.
ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(),
&basic_resolver,
&fast_resolver));
ASSERT_TRUE(fast_resolver.HasModule(&module1));
basic_resolver.UnloadModule(&module1);
fast_resolver.UnloadModule(&module1);
ASSERT_FALSE(fast_resolver.HasModule(&module1));
ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1)));
ASSERT_TRUE(basic_resolver.HasModule(&module1));
// Convert module1 to fast_module.
ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(),
&basic_resolver,
&fast_resolver));
ASSERT_TRUE(fast_resolver.HasModule(&module1));
}
TEST_F(TestFastSourceLineResolver, CompareModule) {
char *symbol_data;
string symbol_data_string;
string filename;
for (int module_index = 0; module_index < 3; ++module_index) {
std::stringstream ss;
ss << testdata_dir << "/module" << module_index << ".out";
filename = ss.str();
ASSERT_TRUE(SourceLineResolverBase::ReadSymbolFile(
&symbol_data, symbol_file(module_index)));
symbol_data_string = symbol_data;
delete symbol_data;
ASSERT_TRUE(module_comparer.Compare(symbol_data_string));
}
}
} // namespace
int main(int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -0,0 +1,302 @@
// Copyright (c) 2010, 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.
//
// module_comparer.cc: ModuleComparer implementation.
// See module_comparer.h for documentation.
//
// Author: lambxsy@google.com (Siyang Xie)
#include "processor/module_comparer.h"
#include <map>
#include <string>
#include "processor/basic_code_module.h"
#include "processor/logging.h"
#include "processor/scoped_ptr.h"
#define ASSERT_TRUE(condition) \
if (!(condition)) { \
BPLOG(ERROR) << "FAIL: " << #condition << " @ " \
<< __FILE__ << ":" << __LINE__; \
return false; \
}
#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))
namespace google_breakpad {
bool ModuleComparer::Compare(const string &symbol_data) {
// Empty CodeModule with only a name "test":
BasicCodeModule code_module(0, 0, "test", "", "", "", "");
// Load BasicSourceLineResolver::Module.
BPLOG(INFO) << "Unserialized size = " << symbol_data.size() << " Bytes";
basic_resolver_->LoadModuleUsingMapBuffer(&code_module, symbol_data);
BasicModule *old_module = dynamic_cast<BasicModule*>(
basic_resolver_->modules_->at("test"));
// Serialize BasicSourceLineResolver::Module.
unsigned int serialized_size = 0;
char *mem = serializer_.Serialize(*old_module, &serialized_size);
ASSERT_TRUE(mem);
BPLOG(INFO) << "Serialized size = " << serialized_size << " Bytes";
// Load FastSourceLineResolver::Module using serialized data.
ASSERT_TRUE(fast_resolver_->LoadModuleUsingMemoryBuffer(&code_module, mem));
FastModule *new_module = dynamic_cast<FastModule*>(
fast_resolver_->modules_->at("test"));
// Compare FastSourceLineResolver::Module with
// BasicSourceLineResolver::Module.
ASSERT_TRUE(CompareModule(old_module, new_module));
// Clean up.
basic_resolver_->UnloadModule(&code_module);
fast_resolver_->UnloadModule(&code_module);
return true;
}
// Traversal the content of module and do comparison
bool ModuleComparer::CompareModule(const BasicModule *basic_module,
const FastModule *fast_module) const {
// Compare name_.
ASSERT_TRUE(basic_module->name_ == fast_module->name_);
// Compare files_:
{
BasicModule::FileMap::const_iterator iter1 = basic_module->files_.begin();
FastModule::FileMap::iterator iter2 = fast_module->files_.begin();
while (iter1 != basic_module->files_.end()
&& iter2 != fast_module->files_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
string tmp(iter2.GetValuePtr());
ASSERT_TRUE(iter1->second == tmp);
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_module->files_.end());
ASSERT_TRUE(iter2 == fast_module->files_.end());
}
// Compare functions_:
{
RangeMap<MemAddr, linked_ptr<BasicFunc> >::MapConstIterator iter1;
StaticRangeMap<MemAddr, FastFunc>::MapConstIterator iter2;
iter1 = basic_module->functions_.map_.begin();
iter2 = fast_module->functions_.map_.begin();
while (iter1 != basic_module->functions_.map_.end()
&& iter2 != fast_module->functions_.map_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
ASSERT_TRUE(CompareFunction(
iter1->second.entry().get(), iter2.GetValuePtr()->entryptr()));
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_module->functions_.map_.end());
ASSERT_TRUE(iter2 == fast_module->functions_.map_.end());
}
// Compare public_symbols_:
{
AddressMap<MemAddr, linked_ptr<BasicPubSymbol> >::MapConstIterator iter1;
StaticAddressMap<MemAddr, FastPubSymbol>::MapConstIterator iter2;
iter1 = basic_module->public_symbols_.map_.begin();
iter2 = fast_module->public_symbols_.map_.begin();
while (iter1 != basic_module->public_symbols_.map_.end()
&& iter2 != fast_module->public_symbols_.map_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
ASSERT_TRUE(ComparePubSymbol(
iter1->second.get(), iter2.GetValuePtr()));
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_module->public_symbols_.map_.end());
ASSERT_TRUE(iter2 == fast_module->public_symbols_.map_.end());
}
// Compare windows_frame_info_[]:
for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) {
ASSERT_TRUE(CompareCRM(&(basic_module->windows_frame_info_[i]),
&(fast_module->windows_frame_info_[i])));
}
// Compare cfi_initial_rules_:
{
RangeMap<MemAddr, string>::MapConstIterator iter1;
StaticRangeMap<MemAddr, char>::MapConstIterator iter2;
iter1 = basic_module->cfi_initial_rules_.map_.begin();
iter2 = fast_module->cfi_initial_rules_.map_.begin();
while (iter1 != basic_module->cfi_initial_rules_.map_.end()
&& iter2 != fast_module->cfi_initial_rules_.map_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
string tmp(iter2.GetValuePtr()->entryptr());
ASSERT_TRUE(iter1->second.entry() == tmp);
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_module->cfi_initial_rules_.map_.end());
ASSERT_TRUE(iter2 == fast_module->cfi_initial_rules_.map_.end());
}
// Compare cfi_delta_rules_:
{
map<MemAddr, string>::const_iterator iter1;
StaticMap<MemAddr, char>::iterator iter2;
iter1 = basic_module->cfi_delta_rules_.begin();
iter2 = fast_module->cfi_delta_rules_.begin();
while (iter1 != basic_module->cfi_delta_rules_.end()
&& iter2 != fast_module->cfi_delta_rules_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
string tmp(iter2.GetValuePtr());
ASSERT_TRUE(iter1->second == tmp);
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_module->cfi_delta_rules_.end());
ASSERT_TRUE(iter2 == fast_module->cfi_delta_rules_.end());
}
return true;
}
bool ModuleComparer::CompareFunction(const BasicFunc *basic_func,
const FastFunc *fast_func_raw) const {
FastFunc* fast_func = new FastFunc();
fast_func->CopyFrom(fast_func_raw);
ASSERT_TRUE(basic_func->name == fast_func->name);
ASSERT_TRUE(basic_func->address == fast_func->address);
ASSERT_TRUE(basic_func->size == fast_func->size);
// compare range map of lines:
RangeMap<MemAddr, linked_ptr<BasicLine> >::MapConstIterator iter1;
StaticRangeMap<MemAddr, FastLine>::MapConstIterator iter2;
iter1 = basic_func->lines.map_.begin();
iter2 = fast_func->lines.map_.begin();
while (iter1 != basic_func->lines.map_.end()
&& iter2 != fast_func->lines.map_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
ASSERT_TRUE(CompareLine(iter1->second.entry().get(),
iter2.GetValuePtr()->entryptr()));
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_func->lines.map_.end());
ASSERT_TRUE(iter2 == fast_func->lines.map_.end());
delete fast_func;
return true;
}
bool ModuleComparer::CompareLine(const BasicLine *basic_line,
const FastLine *fast_line_raw) const {
FastLine *fast_line = new FastLine;
fast_line->CopyFrom(fast_line_raw);
ASSERT_TRUE(basic_line->address == fast_line->address);
ASSERT_TRUE(basic_line->size == fast_line->size);
ASSERT_TRUE(basic_line->source_file_id == fast_line->source_file_id);
ASSERT_TRUE(basic_line->line == fast_line->line);
delete fast_line;
return true;
}
bool ModuleComparer::ComparePubSymbol(const BasicPubSymbol* basic_ps,
const FastPubSymbol* fastps_raw) const {
FastPubSymbol *fast_ps = new FastPubSymbol;
fast_ps->CopyFrom(fastps_raw);
ASSERT_TRUE(basic_ps->name == fast_ps->name);
ASSERT_TRUE(basic_ps->address == fast_ps->address);
ASSERT_TRUE(basic_ps->parameter_size == fast_ps->parameter_size);
delete fast_ps;
return true;
}
bool ModuleComparer::CompareWFI(const WindowsFrameInfo& wfi1,
const WindowsFrameInfo& wfi2) const {
ASSERT_TRUE(wfi1.valid == wfi2.valid);
ASSERT_TRUE(wfi1.prolog_size == wfi2.prolog_size);
ASSERT_TRUE(wfi1.epilog_size == wfi2.epilog_size);
ASSERT_TRUE(wfi1.parameter_size == wfi2.parameter_size);
ASSERT_TRUE(wfi1.saved_register_size == wfi2.saved_register_size);
ASSERT_TRUE(wfi1.local_size == wfi2.local_size);
ASSERT_TRUE(wfi1.max_stack_size == wfi2.max_stack_size);
ASSERT_TRUE(wfi1.allocates_base_pointer == wfi2.allocates_base_pointer);
ASSERT_TRUE(wfi1.program_string == wfi2.program_string);
return true;
}
// Compare ContainedRangeMap
bool ModuleComparer::CompareCRM(
const ContainedRangeMap<MemAddr, linked_ptr<WFI> >* basic_crm,
const StaticContainedRangeMap<MemAddr, char>* fast_crm) const {
ASSERT_TRUE(basic_crm->base_ == fast_crm->base_);
if (!basic_crm->entry_.get() || !fast_crm->entry_ptr_) {
// empty entry:
ASSERT_TRUE(!basic_crm->entry_.get() && !fast_crm->entry_ptr_);
} else {
WFI newwfi;
newwfi.CopyFrom(fast_resolver_->CopyWFI(fast_crm->entry_ptr_));
ASSERT_TRUE(CompareWFI(*(basic_crm->entry_.get()), newwfi));
}
if ((!basic_crm->map_ || basic_crm->map_->empty())
|| fast_crm->map_.empty()) {
ASSERT_TRUE((!basic_crm->map_ || basic_crm->map_->empty())
&& fast_crm->map_.empty());
} else {
ContainedRangeMap<MemAddr, linked_ptr<WFI> >::MapConstIterator iter1;
StaticContainedRangeMap<MemAddr, char>::MapConstIterator iter2;
iter1 = basic_crm->map_->begin();
iter2 = fast_crm->map_.begin();
while (iter1 != basic_crm->map_->end()
&& iter2 != fast_crm->map_.end()) {
ASSERT_TRUE(iter1->first == iter2.GetKey());
StaticContainedRangeMap<MemAddr, char> *child =
new StaticContainedRangeMap<MemAddr, char>(
reinterpret_cast<const char*>(iter2.GetValuePtr()));
ASSERT_TRUE(CompareCRM(iter1->second, child));
delete child;
++iter1;
++iter2;
}
ASSERT_TRUE(iter1 == basic_crm->map_->end());
ASSERT_TRUE(iter2 == fast_crm->map_.end());
}
return true;
}
} // namespace google_breakpad

View file

@ -0,0 +1,98 @@
// Copyright (c) 2010, 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.
//
// module_comparer.h: ModuleComparer reads a string format of symbol file, and
// loads the symbol into both BasicSourceLineResolver::Module and
// FastSourceLineResolve::Module. It then traverses both Modules and compare
// the content of data to verify the correctness of new fast module.
// ModuleCompare class is a tool to verify correctness of a loaded
// FastSourceLineResolver::Module instance, i.e., in-memory representation of
// parsed symbol. ModuleComparer class should be used for testing purpose only,
// e.g., in fast_source_line_resolver_unittest.
//
// Author: lambxsy@google.com (Siyang Xie)
#ifndef PROCESSOR_MODULE_COMPARER_H__
#define PROCESSOR_MODULE_COMPARER_H__
#include <string>
#include "processor/basic_source_line_resolver_types.h"
#include "processor/fast_source_line_resolver_types.h"
#include "processor/module_serializer.h"
#include "processor/windows_frame_info.h"
namespace google_breakpad {
class ModuleComparer {
public:
ModuleComparer(): fast_resolver_(new FastSourceLineResolver),
basic_resolver_(new BasicSourceLineResolver) { }
~ModuleComparer() {
delete fast_resolver_;
delete basic_resolver_;
}
// BasicSourceLineResolver loads its module using the symbol data,
// ModuleSerializer serialize the loaded module into a memory chunk,
// FastSourceLineResolver loads its module using the serialized memory chunk,
// Then, traverse both modules together and compare underlying data
// return true if both modules contain exactly same data.
bool Compare(const string &symbol_data);
private:
typedef BasicSourceLineResolver::Module BasicModule;
typedef FastSourceLineResolver::Module FastModule;
typedef BasicSourceLineResolver::Function BasicFunc;
typedef FastSourceLineResolver::Function FastFunc;
typedef BasicSourceLineResolver::Line BasicLine;
typedef FastSourceLineResolver::Line FastLine;
typedef BasicSourceLineResolver::PublicSymbol BasicPubSymbol;
typedef FastSourceLineResolver::PublicSymbol FastPubSymbol;
typedef WindowsFrameInfo WFI;
bool CompareModule(const BasicModule *oldmodule,
const FastModule *newmodule) const;
bool CompareFunction(const BasicFunc *oldfunc, const FastFunc *newfunc) const;
bool CompareLine(const BasicLine *oldline, const FastLine *newline) const;
bool ComparePubSymbol(const BasicPubSymbol*, const FastPubSymbol*) const;
bool CompareWFI(const WindowsFrameInfo&, const WindowsFrameInfo&) const;
// Compare ContainedRangeMap
bool CompareCRM(const ContainedRangeMap<MemAddr, linked_ptr<WFI> >*,
const StaticContainedRangeMap<MemAddr, char>*) const;
FastSourceLineResolver *fast_resolver_;
BasicSourceLineResolver *basic_resolver_;
ModuleSerializer serializer_;
};
} // namespace google_breakpad
#endif // PROCESSOR_MODULE_COMPARER_H__

View file

@ -36,8 +36,9 @@
#ifndef PROCESSOR_MODULE_FACTORY_H__
#define PROCESSOR_MODULE_FACTORY_H__
#include "processor/source_line_resolver_base_types.h"
#include "processor/basic_source_line_resolver_types.h"
#include "processor/fast_source_line_resolver_types.h"
#include "processor/source_line_resolver_base_types.h"
namespace google_breakpad {
@ -57,6 +58,15 @@ class BasicModuleFactory : public ModuleFactory {
}
};
class FastModuleFactory : public ModuleFactory {
public:
virtual ~FastModuleFactory() { }
virtual FastSourceLineResolver::Module* CreateModule(
const string &name) const {
return new FastSourceLineResolver::Module(name);
}
};
} // namespace google_breakpad
#endif // PROCESSOR_MODULE_FACTORY_H__

View file

@ -96,6 +96,7 @@ class RangeMap {
private:
// Friend declarations.
friend class ModuleComparer;
friend class RangeMapSerializer<AddressType, EntryType>;
class Range {

View file

@ -50,7 +50,6 @@ StaticContainedRangeMap<AddressType, EntryType>::StaticContainedRangeMap(
entry_ptr_(reinterpret_cast<const EntryType *>(
base + sizeof(base_) + sizeof(entry_size_))),
map_(base + sizeof(base_) + sizeof(entry_size_) + entry_size_) {
if (entry_size_ == 0)
entry_ptr_ = NULL;
}

View file

@ -314,7 +314,7 @@ class TestValidMap : public ::testing::Test {
TEST_F(TestValidMap, TestEmptyMap) {
int test_case = 0;
// Assert memory size allocated during serialization is correct.
ASSERT_EQ(correct_size[test_case], size[test_case]);;
ASSERT_EQ(correct_size[test_case], size[test_case]);
// Sanity check of serialized data:
ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure());
@ -365,7 +365,7 @@ TEST_F(TestValidMap, Test100Elements) {
TEST_F(TestValidMap, Test1000RandomElements) {
int test_case = 3;
// Assert memory size allocated during serialization is correct.
ASSERT_EQ(correct_size[test_case], size[test_case]);;
ASSERT_EQ(correct_size[test_case], size[test_case]);
// Sanity check of serialized data:
ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure());

22151
src/processor/testdata/module0.out vendored Normal file

File diff suppressed because it is too large Load diff