Refactor source line resolver, add interface in supplier and resolver.
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@711 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
d35f113d02
commit
5b117cf53a
24 changed files with 1021 additions and 418 deletions
11
Makefile.am
11
Makefile.am
|
@ -90,6 +90,7 @@ src_libbreakpad_a_SOURCES = \
|
||||||
src/google_breakpad/processor/minidump_processor.h \
|
src/google_breakpad/processor/minidump_processor.h \
|
||||||
src/google-breakpad/processor/network_source_line_resolver.h \
|
src/google-breakpad/processor/network_source_line_resolver.h \
|
||||||
src/google_breakpad/processor/process_state.h \
|
src/google_breakpad/processor/process_state.h \
|
||||||
|
src/google_breakpad/processor/source_line_resolver_base.h \
|
||||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||||
src/google_breakpad/processor/stack_frame.h \
|
src/google_breakpad/processor/stack_frame.h \
|
||||||
src/google_breakpad/processor/stack_frame_cpu.h \
|
src/google_breakpad/processor/stack_frame_cpu.h \
|
||||||
|
@ -101,6 +102,7 @@ src_libbreakpad_a_SOURCES = \
|
||||||
src/processor/basic_code_module.h \
|
src/processor/basic_code_module.h \
|
||||||
src/processor/basic_code_modules.cc \
|
src/processor/basic_code_modules.cc \
|
||||||
src/processor/basic_code_modules.h \
|
src/processor/basic_code_modules.h \
|
||||||
|
src/processor/basic_source_line_resolver_types.h \
|
||||||
src/processor/basic_source_line_resolver.cc \
|
src/processor/basic_source_line_resolver.cc \
|
||||||
src/processor/binarystream.h \
|
src/processor/binarystream.h \
|
||||||
src/processor/binarystream.cc \
|
src/processor/binarystream.cc \
|
||||||
|
@ -134,6 +136,8 @@ src_libbreakpad_a_SOURCES = \
|
||||||
src/processor/simple_symbol_supplier.cc \
|
src/processor/simple_symbol_supplier.cc \
|
||||||
src/processor/simple_symbol_supplier.h \
|
src/processor/simple_symbol_supplier.h \
|
||||||
src/processor/windows_frame_info.h \
|
src/processor/windows_frame_info.h \
|
||||||
|
src/processor/source_line_resolver_base_types.h \
|
||||||
|
src/processor/source_line_resolver_base.cc \
|
||||||
src/processor/stackwalker.cc \
|
src/processor/stackwalker.cc \
|
||||||
src/processor/stackwalker_amd64.cc \
|
src/processor/stackwalker_amd64.cc \
|
||||||
src/processor/stackwalker_amd64.h \
|
src/processor/stackwalker_amd64.h \
|
||||||
|
@ -322,6 +326,7 @@ src_processor_basic_source_line_resolver_unittest_LDADD = \
|
||||||
src/processor/cfi_frame_info.o \
|
src/processor/cfi_frame_info.o \
|
||||||
src/processor/pathname_stripper.o \
|
src/processor/pathname_stripper.o \
|
||||||
src/processor/logging.o \
|
src/processor/logging.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/tokenize.o
|
src/processor/tokenize.o
|
||||||
|
|
||||||
src_processor_cfi_frame_info_unittest_SOURCES = \
|
src_processor_cfi_frame_info_unittest_SOURCES = \
|
||||||
|
@ -370,6 +375,7 @@ src_processor_exploitability_unittest_LDADD = \
|
||||||
src/processor/logging.o \
|
src/processor/logging.o \
|
||||||
src/processor/minidump.o \
|
src/processor/minidump.o \
|
||||||
src/processor/pathname_stripper.o \
|
src/processor/pathname_stripper.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/stackwalker.o \
|
src/processor/stackwalker.o \
|
||||||
src/processor/stackwalker_amd64.o \
|
src/processor/stackwalker_amd64.o \
|
||||||
src/processor/stackwalker_arm.o \
|
src/processor/stackwalker_arm.o \
|
||||||
|
@ -417,6 +423,7 @@ src_processor_minidump_processor_unittest_LDADD = \
|
||||||
src/processor/minidump.o \
|
src/processor/minidump.o \
|
||||||
src/processor/pathname_stripper.o \
|
src/processor/pathname_stripper.o \
|
||||||
src/processor/process_state.o \
|
src/processor/process_state.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/stackwalker.o \
|
src/processor/stackwalker.o \
|
||||||
src/processor/stackwalker_amd64.o \
|
src/processor/stackwalker_amd64.o \
|
||||||
src/processor/stackwalker_arm.o \
|
src/processor/stackwalker_arm.o \
|
||||||
|
@ -492,6 +499,7 @@ src_processor_network_source_line_resolver_server_unittest_LDADD = \
|
||||||
src/processor/pathname_stripper.o \
|
src/processor/pathname_stripper.o \
|
||||||
src/processor/process_state.o \
|
src/processor/process_state.o \
|
||||||
src/processor/simple_symbol_supplier.o \
|
src/processor/simple_symbol_supplier.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/stackwalker.o \
|
src/processor/stackwalker.o \
|
||||||
src/processor/stackwalker_amd64.o \
|
src/processor/stackwalker_amd64.o \
|
||||||
src/processor/stackwalker_arm.o \
|
src/processor/stackwalker_arm.o \
|
||||||
|
@ -563,6 +571,7 @@ src_processor_stackwalker_selftest_LDADD = \
|
||||||
src/processor/logging.o \
|
src/processor/logging.o \
|
||||||
src/processor/minidump.o \
|
src/processor/minidump.o \
|
||||||
src/processor/pathname_stripper.o \
|
src/processor/pathname_stripper.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/stackwalker.o \
|
src/processor/stackwalker.o \
|
||||||
src/processor/stackwalker_amd64.o \
|
src/processor/stackwalker_amd64.o \
|
||||||
src/processor/stackwalker_arm.o \
|
src/processor/stackwalker_arm.o \
|
||||||
|
@ -676,6 +685,7 @@ src_processor_minidump_stackwalk_LDADD = \
|
||||||
src/processor/process_state.o \
|
src/processor/process_state.o \
|
||||||
src/processor/network_source_line_resolver.o \
|
src/processor/network_source_line_resolver.o \
|
||||||
src/processor/simple_symbol_supplier.o \
|
src/processor/simple_symbol_supplier.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/stackwalker.o \
|
src/processor/stackwalker.o \
|
||||||
src/processor/stackwalker_amd64.o \
|
src/processor/stackwalker_amd64.o \
|
||||||
src/processor/stackwalker_arm.o \
|
src/processor/stackwalker_arm.o \
|
||||||
|
@ -697,6 +707,7 @@ src_processor_source_daemon_LDADD = \
|
||||||
src/processor/network_source_line_server.o \
|
src/processor/network_source_line_server.o \
|
||||||
src/processor/pathname_stripper.o \
|
src/processor/pathname_stripper.o \
|
||||||
src/processor/simple_symbol_supplier.o \
|
src/processor/simple_symbol_supplier.o \
|
||||||
|
src/processor/source_line_resolver_base.o \
|
||||||
src/processor/tokenize.o \
|
src/processor/tokenize.o \
|
||||||
src/processor/udp_network.o
|
src/processor/udp_network.o
|
||||||
endif !DISABLE_PROCESSOR
|
endif !DISABLE_PROCESSOR
|
||||||
|
|
28
Makefile.in
28
Makefile.in
|
@ -192,6 +192,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
||||||
src/google_breakpad/processor/minidump_processor.h \
|
src/google_breakpad/processor/minidump_processor.h \
|
||||||
src/google-breakpad/processor/network_source_line_resolver.h \
|
src/google-breakpad/processor/network_source_line_resolver.h \
|
||||||
src/google_breakpad/processor/process_state.h \
|
src/google_breakpad/processor/process_state.h \
|
||||||
|
src/google_breakpad/processor/source_line_resolver_base.h \
|
||||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||||
src/google_breakpad/processor/stack_frame.h \
|
src/google_breakpad/processor/stack_frame.h \
|
||||||
src/google_breakpad/processor/stack_frame_cpu.h \
|
src/google_breakpad/processor/stack_frame_cpu.h \
|
||||||
|
@ -202,6 +203,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
||||||
src/processor/basic_code_module.h \
|
src/processor/basic_code_module.h \
|
||||||
src/processor/basic_code_modules.cc \
|
src/processor/basic_code_modules.cc \
|
||||||
src/processor/basic_code_modules.h \
|
src/processor/basic_code_modules.h \
|
||||||
|
src/processor/basic_source_line_resolver_types.h \
|
||||||
src/processor/basic_source_line_resolver.cc \
|
src/processor/basic_source_line_resolver.cc \
|
||||||
src/processor/binarystream.h src/processor/binarystream.cc \
|
src/processor/binarystream.h src/processor/binarystream.cc \
|
||||||
src/processor/call_stack.cc src/processor/cfi_frame_info.cc \
|
src/processor/call_stack.cc src/processor/cfi_frame_info.cc \
|
||||||
|
@ -228,6 +230,8 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
||||||
src/processor/simple_symbol_supplier.cc \
|
src/processor/simple_symbol_supplier.cc \
|
||||||
src/processor/simple_symbol_supplier.h \
|
src/processor/simple_symbol_supplier.h \
|
||||||
src/processor/windows_frame_info.h \
|
src/processor/windows_frame_info.h \
|
||||||
|
src/processor/source_line_resolver_base_types.h \
|
||||||
|
src/processor/source_line_resolver_base.cc \
|
||||||
src/processor/stackwalker.cc \
|
src/processor/stackwalker.cc \
|
||||||
src/processor/stackwalker_amd64.cc \
|
src/processor/stackwalker_amd64.cc \
|
||||||
src/processor/stackwalker_amd64.h \
|
src/processor/stackwalker_amd64.h \
|
||||||
|
@ -260,6 +264,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.$(OBJEXT) \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.$(OBJEXT) \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.$(OBJEXT) \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.$(OBJEXT) \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.$(OBJEXT) \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.$(OBJEXT) \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.$(OBJEXT) \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.$(OBJEXT) \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.$(OBJEXT) \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.$(OBJEXT) \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.$(OBJEXT) \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.$(OBJEXT) \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.$(OBJEXT) \
|
||||||
|
@ -414,6 +419,7 @@ src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_b
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.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/tokenize.o
|
||||||
am__src_processor_binarystream_unittest_SOURCES_DIST = \
|
am__src_processor_binarystream_unittest_SOURCES_DIST = \
|
||||||
src/processor/binarystream_unittest.cc \
|
src/processor/binarystream_unittest.cc \
|
||||||
|
@ -487,6 +493,7 @@ src_processor_exploitability_unittest_OBJECTS = \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -527,6 +534,7 @@ src_processor_minidump_processor_unittest_OBJECTS = \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -556,6 +564,7 @@ src_processor_minidump_stackwalk_OBJECTS = \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -610,6 +619,7 @@ src_processor_network_source_line_resolver_server_unittest_OBJECTS = $(am_src_pr
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -688,6 +698,7 @@ src_processor_source_daemon_OBJECTS = \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/udp_network.o
|
@DISABLE_PROCESSOR_FALSE@ src/processor/udp_network.o
|
||||||
am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST = \
|
am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST = \
|
||||||
|
@ -735,6 +746,7 @@ src_processor_stackwalker_selftest_OBJECTS = \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -1021,6 +1033,7 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump_processor.h \
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump_processor.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/google-breakpad/processor/network_source_line_resolver.h \
|
@DISABLE_PROCESSOR_FALSE@ src/google-breakpad/processor/network_source_line_resolver.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/process_state.h \
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/process_state.h \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_base.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_interface.h \
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame.h \
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_cpu.h \
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_cpu.h \
|
||||||
|
@ -1032,6 +1045,7 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_module.h \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_module.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.cc \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.cc \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.h \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.h \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_types.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.cc \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.cc \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.h \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.cc \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.cc \
|
||||||
|
@ -1065,6 +1079,8 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.cc \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.cc \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.h \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.h \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/windows_frame_info.h \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/windows_frame_info.h \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base_types.h \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.cc \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.cc \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.cc \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.cc \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.cc \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.h \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.h \
|
||||||
|
@ -1201,6 +1217,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.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/tokenize.o
|
||||||
|
|
||||||
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \
|
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \
|
||||||
|
@ -1254,6 +1271,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -1305,6 +1323,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -1386,6 +1405,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -1465,6 +1485,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -1585,6 +1606,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||||
|
@ -1607,6 +1629,7 @@ TESTS_ENVIRONMENT =
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||||
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
||||||
@DISABLE_PROCESSOR_FALSE@ src/processor/udp_network.o
|
@DISABLE_PROCESSOR_FALSE@ src/processor/udp_network.o
|
||||||
|
|
||||||
|
@ -1946,6 +1969,9 @@ src/processor/process_state.$(OBJEXT): src/processor/$(am__dirstamp) \
|
||||||
src/processor/simple_symbol_supplier.$(OBJEXT): \
|
src/processor/simple_symbol_supplier.$(OBJEXT): \
|
||||||
src/processor/$(am__dirstamp) \
|
src/processor/$(am__dirstamp) \
|
||||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
src/processor/source_line_resolver_base.$(OBJEXT): \
|
||||||
|
src/processor/$(am__dirstamp) \
|
||||||
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
src/processor/stackwalker.$(OBJEXT): src/processor/$(am__dirstamp) \
|
src/processor/stackwalker.$(OBJEXT): src/processor/$(am__dirstamp) \
|
||||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
src/processor/stackwalker_amd64.$(OBJEXT): \
|
src/processor/stackwalker_amd64.$(OBJEXT): \
|
||||||
|
@ -2475,6 +2501,7 @@ mostlyclean-compile:
|
||||||
-rm -f src/processor/range_map_unittest.$(OBJEXT)
|
-rm -f src/processor/range_map_unittest.$(OBJEXT)
|
||||||
-rm -f src/processor/simple_symbol_supplier.$(OBJEXT)
|
-rm -f src/processor/simple_symbol_supplier.$(OBJEXT)
|
||||||
-rm -f src/processor/source_daemon.$(OBJEXT)
|
-rm -f src/processor/source_daemon.$(OBJEXT)
|
||||||
|
-rm -f src/processor/source_line_resolver_base.$(OBJEXT)
|
||||||
-rm -f src/processor/src_client_linux_linux_client_unittest-basic_code_modules.$(OBJEXT)
|
-rm -f src/processor/src_client_linux_linux_client_unittest-basic_code_modules.$(OBJEXT)
|
||||||
-rm -f src/processor/src_client_linux_linux_client_unittest-logging.$(OBJEXT)
|
-rm -f src/processor/src_client_linux_linux_client_unittest-logging.$(OBJEXT)
|
||||||
-rm -f src/processor/src_client_linux_linux_client_unittest-minidump.$(OBJEXT)
|
-rm -f src/processor/src_client_linux_linux_client_unittest-minidump.$(OBJEXT)
|
||||||
|
@ -2615,6 +2642,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/range_map_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/range_map_unittest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_daemon.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_daemon.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_line_resolver_base.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-basic_code_modules.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-basic_code_modules.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-logging.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-logging.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump.Po@am__quote@
|
||||||
|
|
|
@ -27,59 +27,56 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// BasicSourceLineResolver implements SourceLineResolverInterface, using
|
// basic_source_line_resolver.h: BasicSourceLineResolver is derived from
|
||||||
// address map files produced by a compatible writer, e.g. PDBSourceLineWriter.
|
// SourceLineResolverBase, and is a concrete implementation of
|
||||||
|
// SourceLineResolverInterface, using address map files produced by a
|
||||||
|
// compatible writer, e.g. PDBSourceLineWriter.
|
||||||
|
//
|
||||||
|
// see "processor/source_line_resolver_base.h"
|
||||||
|
// and "source_line_resolver_interface.h" for more documentation.
|
||||||
|
|
||||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
||||||
#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::map;
|
using std::map;
|
||||||
|
|
||||||
class BasicSourceLineResolver : public SourceLineResolverInterface {
|
class BasicSourceLineResolver : public SourceLineResolverBase {
|
||||||
public:
|
public:
|
||||||
BasicSourceLineResolver();
|
BasicSourceLineResolver();
|
||||||
virtual ~BasicSourceLineResolver();
|
virtual ~BasicSourceLineResolver() { }
|
||||||
|
|
||||||
// SourceLineResolverInterface methods, see source_line_resolver_interface.h
|
using SourceLineResolverBase::LoadModule;
|
||||||
// for more details.
|
using SourceLineResolverBase::LoadModuleUsingMapBuffer;
|
||||||
|
using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
|
||||||
// Adds a module to this resolver, returning true on success.
|
using SourceLineResolverBase::UnloadModule;
|
||||||
// The given map_file is read into memory, and its symbols will be
|
using SourceLineResolverBase::HasModule;
|
||||||
// retained until the BasicSourceLineResolver is destroyed.
|
using SourceLineResolverBase::FillSourceLineInfo;
|
||||||
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
using SourceLineResolverBase::FindWindowsFrameInfo;
|
||||||
|
using SourceLineResolverBase::FindCFIFrameInfo;
|
||||||
// Exactly the same as above, except the given map_buffer is used
|
|
||||||
// for symbols.
|
|
||||||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
|
||||||
const string &map_buffer);
|
|
||||||
|
|
||||||
void UnloadModule(const CodeModule *module);
|
|
||||||
virtual bool HasModule(const CodeModule *module);
|
|
||||||
virtual void FillSourceLineInfo(StackFrame *frame);
|
|
||||||
virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame);
|
|
||||||
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class T> class MemAddrMap;
|
// friend declarations:
|
||||||
struct Line;
|
friend class BasicModuleFactory;
|
||||||
|
|
||||||
|
// Function derives from SourceLineResolverBase::Function.
|
||||||
struct Function;
|
struct Function;
|
||||||
struct PublicSymbol;
|
// Module implements SourceLineResolverBase::Module interface.
|
||||||
struct File;
|
|
||||||
struct CompareString {
|
|
||||||
bool operator()(const string &s1, const string &s2) const;
|
|
||||||
};
|
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
// All of the modules we've loaded
|
// Helper method.
|
||||||
typedef map<string, Module*, CompareString> ModuleMap;
|
virtual void DeleteDataAfterLoad(char *symbol_data);
|
||||||
ModuleMap *modules_;
|
// No-op helper methods.
|
||||||
|
virtual void DeleteDataUnload(const CodeModule *module) { }
|
||||||
|
virtual void ClearLocalMemory() { }
|
||||||
|
virtual void StoreDataBeforeLoad(const CodeModule *module,
|
||||||
|
char *symbol_data) { }
|
||||||
|
|
||||||
// Disallow unwanted copy ctor and assignment operator
|
// Disallow unwanted copy ctor and assignment operator
|
||||||
BasicSourceLineResolver(const BasicSourceLineResolver&);
|
BasicSourceLineResolver(const BasicSourceLineResolver&);
|
||||||
|
|
|
@ -37,8 +37,8 @@
|
||||||
// An implementation of the server side of the protocol is provided there
|
// An implementation of the server side of the protocol is provided there
|
||||||
// as NetworkSourceLineServer.
|
// as NetworkSourceLineServer.
|
||||||
|
|
||||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_
|
#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H__
|
||||||
#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_
|
#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H__
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
@ -81,6 +81,8 @@ class NetworkSourceLineResolver : public SourceLineResolverInterface,
|
||||||
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
||||||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||||
const string &map_buffer);
|
const string &map_buffer);
|
||||||
|
virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
|
||||||
|
char *memory_buffer);
|
||||||
|
|
||||||
void UnloadModule(const CodeModule *module);
|
void UnloadModule(const CodeModule *module);
|
||||||
|
|
||||||
|
@ -104,6 +106,11 @@ class NetworkSourceLineResolver : public SourceLineResolverInterface,
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
string *symbol_file,
|
string *symbol_file,
|
||||||
string *symbol_data);
|
string *symbol_data);
|
||||||
|
// Similar as the above GetSymbolFile() method, see the comment above.
|
||||||
|
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int wait_milliseconds_;
|
int wait_milliseconds_;
|
||||||
|
@ -165,4 +172,4 @@ class NetworkSourceLineResolver : public SourceLineResolverInterface,
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
||||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_
|
#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H__
|
||||||
|
|
117
src/google_breakpad/processor/source_line_resolver_base.h
Normal file
117
src/google_breakpad/processor/source_line_resolver_base.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// source_line_resolver_base.h: SourceLineResolverBase, an (incomplete)
|
||||||
|
// implementation of SourceLineResolverInterface. It serves as a common base
|
||||||
|
// class for concrete implementations: FastSourceLineResolver and
|
||||||
|
// BasicSourceLineResolver. It is designed for refactoring that removes
|
||||||
|
// code redundancy in the two concrete source line resolver classes.
|
||||||
|
//
|
||||||
|
// See "google_breakpad/processor/source_line_resolver_interface.h" for more
|
||||||
|
// documentation.
|
||||||
|
|
||||||
|
// Author: Siyang Xie (lambxsy@google.com)
|
||||||
|
|
||||||
|
#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
|
||||||
|
#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
|
||||||
|
// Forward declaration.
|
||||||
|
// ModuleFactory is a simple factory interface for creating a Module instance
|
||||||
|
// at run-time.
|
||||||
|
class ModuleFactory;
|
||||||
|
|
||||||
|
class SourceLineResolverBase : public SourceLineResolverInterface {
|
||||||
|
public:
|
||||||
|
// Read the symbol_data from a file with given file_name.
|
||||||
|
// The part of code was originally in BasicSourceLineResolver::Module's
|
||||||
|
// LoadMap() method.
|
||||||
|
static bool ReadSymbolFile(char **symbol_data, const string &file_name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Users are not allowed create SourceLineResolverBase instance directly.
|
||||||
|
SourceLineResolverBase(ModuleFactory *module_factory);
|
||||||
|
virtual ~SourceLineResolverBase();
|
||||||
|
|
||||||
|
// Virtual methods inherited from SourceLineResolverInterface.
|
||||||
|
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
||||||
|
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||||
|
const string &map_buffer);
|
||||||
|
virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
|
||||||
|
char *memory_buffer);
|
||||||
|
virtual void UnloadModule(const CodeModule *module);
|
||||||
|
virtual bool HasModule(const CodeModule *module);
|
||||||
|
virtual void FillSourceLineInfo(StackFrame *frame);
|
||||||
|
virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame);
|
||||||
|
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame);
|
||||||
|
|
||||||
|
// Helper methods to manage C-String format symbol data.
|
||||||
|
virtual void StoreDataBeforeLoad(const CodeModule *module, char *symbol_data);
|
||||||
|
virtual void DeleteDataAfterLoad(char *symbol_data);
|
||||||
|
virtual void DeleteDataUnload(const CodeModule *module);
|
||||||
|
virtual void ClearLocalMemory();
|
||||||
|
|
||||||
|
// Nested structs and classes.
|
||||||
|
struct Line;
|
||||||
|
struct Function;
|
||||||
|
struct PublicSymbol;
|
||||||
|
struct CompareString {
|
||||||
|
bool operator()(const string &s1, const string &s2) const;
|
||||||
|
};
|
||||||
|
// Module is an interface for an in-memory symbol file.
|
||||||
|
class Module;
|
||||||
|
class AutoFileCloser;
|
||||||
|
|
||||||
|
// All of the modules we've loaded
|
||||||
|
typedef map<string, Module*, CompareString> ModuleMap;
|
||||||
|
ModuleMap *modules_;
|
||||||
|
|
||||||
|
// Creates a concrete module at run-time.
|
||||||
|
ModuleFactory *module_factory_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// ModuleFactory needs to have access to protected type Module.
|
||||||
|
friend class ModuleFactory;
|
||||||
|
|
||||||
|
// Disallow unwanted copy ctor and assignment operator
|
||||||
|
SourceLineResolverBase(const SourceLineResolverBase&);
|
||||||
|
void operator=(const SourceLineResolverBase&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
|
|
@ -64,6 +64,12 @@ class SourceLineResolverInterface {
|
||||||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||||
const string &map_buffer) = 0;
|
const string &map_buffer) = 0;
|
||||||
|
|
||||||
|
// Add an interface to load symbol using C-String data insteading string.
|
||||||
|
// This is useful in the optimization design for avoiding unnecessary copying
|
||||||
|
// of symbol data, in order to improve memory efficiency.
|
||||||
|
virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
|
||||||
|
char *memory_buffer) = 0;
|
||||||
|
|
||||||
// Request that the specified module be unloaded from this resolver.
|
// Request that the specified module be unloaded from this resolver.
|
||||||
// A resolver may choose to ignore such a request.
|
// A resolver may choose to ignore such a request.
|
||||||
virtual void UnloadModule(const CodeModule *module) = 0;
|
virtual void UnloadModule(const CodeModule *module) = 0;
|
||||||
|
|
|
@ -75,6 +75,15 @@ class SymbolSupplier {
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
string *symbol_file,
|
string *symbol_file,
|
||||||
string *symbol_data) = 0;
|
string *symbol_data) = 0;
|
||||||
|
|
||||||
|
// Same as above, except places symbol data into symbol_data as C-string in
|
||||||
|
// dynamically allocated memory. Using C-string as type of symbol data enables
|
||||||
|
// passing data by pointer, and thus avoids unncessary copying of data (to
|
||||||
|
// improve memory efficiency).
|
||||||
|
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// basic_source_line_resolver.cc: BasicSourceLineResolver implementation.
|
||||||
|
//
|
||||||
|
// See basic_source_line_resolver.h and basic_source_line_resolver_types.h
|
||||||
|
// for documentation.
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -37,17 +43,10 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "processor/address_map-inl.h"
|
|
||||||
#include "processor/contained_range_map-inl.h"
|
|
||||||
#include "processor/range_map-inl.h"
|
|
||||||
|
|
||||||
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||||
#include "google_breakpad/processor/code_module.h"
|
#include "processor/basic_source_line_resolver_types.h"
|
||||||
#include "google_breakpad/processor/stack_frame.h"
|
#include "processor/module_factory.h"
|
||||||
#include "processor/cfi_frame_info.h"
|
|
||||||
#include "processor/linked_ptr.h"
|
|
||||||
#include "processor/scoped_ptr.h"
|
|
||||||
#include "processor/windows_frame_info.h"
|
|
||||||
#include "processor/tokenize.h"
|
#include "processor/tokenize.h"
|
||||||
|
|
||||||
using std::map;
|
using std::map;
|
||||||
|
@ -58,299 +57,33 @@ namespace google_breakpad {
|
||||||
|
|
||||||
static const char *kWhitespace = " \r\n";
|
static const char *kWhitespace = " \r\n";
|
||||||
|
|
||||||
struct BasicSourceLineResolver::Line {
|
BasicSourceLineResolver::BasicSourceLineResolver() :
|
||||||
Line(MemAddr addr, MemAddr code_size, int file_id, int source_line)
|
SourceLineResolverBase(new BasicModuleFactory) { }
|
||||||
: address(addr)
|
|
||||||
, size(code_size)
|
|
||||||
, source_file_id(file_id)
|
|
||||||
, line(source_line) { }
|
|
||||||
|
|
||||||
MemAddr address;
|
void BasicSourceLineResolver::DeleteDataAfterLoad(char *symbol_data) {
|
||||||
MemAddr size;
|
// Always delete allocated memory after loading symbol.
|
||||||
int source_file_id;
|
delete symbol_data;
|
||||||
int line;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BasicSourceLineResolver::Function {
|
|
||||||
Function(const string &function_name,
|
|
||||||
MemAddr function_address,
|
|
||||||
MemAddr code_size,
|
|
||||||
int set_parameter_size)
|
|
||||||
: name(function_name), address(function_address), size(code_size),
|
|
||||||
parameter_size(set_parameter_size) { }
|
|
||||||
|
|
||||||
string name;
|
|
||||||
MemAddr address;
|
|
||||||
MemAddr size;
|
|
||||||
|
|
||||||
// The size of parameters passed to this function on the stack.
|
|
||||||
int parameter_size;
|
|
||||||
|
|
||||||
RangeMap< MemAddr, linked_ptr<Line> > lines;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BasicSourceLineResolver::PublicSymbol {
|
|
||||||
PublicSymbol(const string& set_name,
|
|
||||||
MemAddr set_address,
|
|
||||||
int set_parameter_size)
|
|
||||||
: name(set_name),
|
|
||||||
address(set_address),
|
|
||||||
parameter_size(set_parameter_size) {}
|
|
||||||
|
|
||||||
string name;
|
|
||||||
MemAddr address;
|
|
||||||
|
|
||||||
// If the public symbol is used as a function entry point, parameter_size
|
|
||||||
// is set to the size of the parameters passed to the funciton on the
|
|
||||||
// stack, if known.
|
|
||||||
int parameter_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BasicSourceLineResolver::Module {
|
|
||||||
public:
|
|
||||||
Module(const string &name) : name_(name) { }
|
|
||||||
|
|
||||||
// Loads the given map file, returning true on success. Reads the
|
|
||||||
// map file into memory and calls LoadMapFromBuffer
|
|
||||||
bool LoadMap(const string &map_file);
|
|
||||||
|
|
||||||
// Loads a map from the given buffer, returning true on success
|
|
||||||
bool LoadMapFromBuffer(const string &map_buffer);
|
|
||||||
|
|
||||||
// Looks up the given relative address, and fills the StackFrame struct
|
|
||||||
// with the result.
|
|
||||||
void LookupAddress(StackFrame *frame) const;
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
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.
|
|
||||||
CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class BasicSourceLineResolver;
|
|
||||||
typedef map<int, string> FileMap;
|
|
||||||
|
|
||||||
// Parses a file declaration
|
|
||||||
bool ParseFile(char *file_line);
|
|
||||||
|
|
||||||
// Parses a function declaration, returning a new Function object.
|
|
||||||
Function* ParseFunction(char *function_line);
|
|
||||||
|
|
||||||
// Parses a line declaration, returning a new Line object.
|
|
||||||
Line* ParseLine(char *line_line);
|
|
||||||
|
|
||||||
// Parses a PUBLIC symbol declaration, storing it in public_symbols_.
|
|
||||||
// Returns false if an error occurs.
|
|
||||||
bool ParsePublicSymbol(char *public_line);
|
|
||||||
|
|
||||||
// Parses a STACK WIN or STACK CFI frame info declaration, storing
|
|
||||||
// it in the appropriate table.
|
|
||||||
bool ParseStackInfo(char *stack_info_line);
|
|
||||||
|
|
||||||
// Parses a STACK CFI record, storing it in cfi_frame_info_.
|
|
||||||
bool ParseCFIFrameInfo(char *stack_info_line);
|
|
||||||
|
|
||||||
// Parse RULE_SET, a series of rules of the sort appearing in STACK
|
|
||||||
// CFI records, and store the given rules in FRAME_INFO.
|
|
||||||
bool ParseCFIRuleSet(const string &rule_set, CFIFrameInfo *frame_info) const;
|
|
||||||
|
|
||||||
string name_;
|
|
||||||
FileMap files_;
|
|
||||||
RangeMap< MemAddr, linked_ptr<Function> > functions_;
|
|
||||||
AddressMap< MemAddr, linked_ptr<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.
|
|
||||||
ContainedRangeMap< MemAddr, linked_ptr<WindowsFrameInfo> >
|
|
||||||
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.
|
|
||||||
RangeMap<MemAddr, string> 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).
|
|
||||||
map<MemAddr, string> cfi_delta_rules_;
|
|
||||||
};
|
|
||||||
|
|
||||||
BasicSourceLineResolver::BasicSourceLineResolver() : modules_(new ModuleMap) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicSourceLineResolver::~BasicSourceLineResolver() {
|
bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
|
||||||
ModuleMap::iterator it;
|
|
||||||
for (it = modules_->begin(); it != modules_->end(); ++it) {
|
|
||||||
delete it->second;
|
|
||||||
}
|
|
||||||
delete modules_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BasicSourceLineResolver::LoadModule(const CodeModule *module,
|
|
||||||
const string &map_file) {
|
|
||||||
if (module == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Make sure we don't already have a module with the given name.
|
|
||||||
if (modules_->find(module->code_file()) != modules_->end()) {
|
|
||||||
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
|
||||||
<< " already loaded";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
|
||||||
<< " from " << map_file;
|
|
||||||
|
|
||||||
Module *basic_module = new Module(module->code_file());
|
|
||||||
if (!basic_module->LoadMap(map_file)) {
|
|
||||||
delete basic_module;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
modules_->insert(make_pair(module->code_file(), basic_module));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BasicSourceLineResolver::LoadModuleUsingMapBuffer(
|
|
||||||
const CodeModule *module,
|
|
||||||
const string &map_buffer) {
|
|
||||||
if (!module)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Make sure we don't already have a module with the given name.
|
|
||||||
if (modules_->find(module->code_file()) != modules_->end()) {
|
|
||||||
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
|
||||||
<< " already loaded";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
|
||||||
<< " from buffer";
|
|
||||||
|
|
||||||
Module *basic_module = new Module(module->code_file());
|
|
||||||
if (!basic_module->LoadMapFromBuffer(map_buffer)) {
|
|
||||||
delete basic_module;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
modules_->insert(make_pair(module->code_file(), basic_module));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BasicSourceLineResolver::UnloadModule(const CodeModule *module)
|
|
||||||
{
|
|
||||||
if (!module)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ModuleMap::iterator iter = modules_->find(module->code_file());
|
|
||||||
if (iter != modules_->end()) {
|
|
||||||
Module *basic_module = iter->second;
|
|
||||||
modules_->erase(iter);
|
|
||||||
delete basic_module;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BasicSourceLineResolver::HasModule(const CodeModule *module) {
|
|
||||||
if (!module)
|
|
||||||
return false;
|
|
||||||
return modules_->find(module->code_file()) != modules_->end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BasicSourceLineResolver::FillSourceLineInfo(StackFrame *frame) {
|
|
||||||
if (frame->module) {
|
|
||||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
|
||||||
if (it != modules_->end()) {
|
|
||||||
it->second->LookupAddress(frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowsFrameInfo *BasicSourceLineResolver::FindWindowsFrameInfo(
|
|
||||||
const StackFrame *frame) {
|
|
||||||
if (frame->module) {
|
|
||||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
|
||||||
if (it != modules_->end()) {
|
|
||||||
return it->second->FindWindowsFrameInfo(frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFIFrameInfo *BasicSourceLineResolver::FindCFIFrameInfo(
|
|
||||||
const StackFrame *frame) {
|
|
||||||
if (frame->module) {
|
|
||||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
|
||||||
if (it != modules_->end()) {
|
|
||||||
return it->second->FindCFIFrameInfo(frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AutoFileCloser {
|
|
||||||
public:
|
|
||||||
AutoFileCloser(FILE *file) : file_(file) {}
|
|
||||||
~AutoFileCloser() {
|
|
||||||
if (file_)
|
|
||||||
fclose(file_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FILE *file_;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool BasicSourceLineResolver::Module::LoadMapFromBuffer(
|
|
||||||
const string &map_buffer) {
|
|
||||||
linked_ptr<Function> cur_func;
|
linked_ptr<Function> cur_func;
|
||||||
int line_number = 0;
|
int line_number = 0;
|
||||||
const char *map_buffer_c_str = map_buffer.c_str();
|
|
||||||
char *save_ptr;
|
char *save_ptr;
|
||||||
|
size_t map_buffer_length = strlen(memory_buffer);
|
||||||
// set up our input buffer as a c-style string so we
|
|
||||||
// can we use strtok()
|
|
||||||
// have to copy because modifying the result of string::c_str is not
|
|
||||||
// permitted
|
|
||||||
size_t map_buffer_length = strlen(map_buffer_c_str);
|
|
||||||
|
|
||||||
// If the length is 0, we can still pretend we have a symbol file. This is
|
// If the length is 0, we can still pretend we have a symbol file. This is
|
||||||
// for scenarios that want to test symbol lookup, but don't necessarily care if
|
// for scenarios that want to test symbol lookup, but don't necessarily care
|
||||||
// certain modules do not have any information, like system libraries.
|
// if certain modules do not have any information, like system libraries.
|
||||||
if (map_buffer_length == 0) {
|
if (map_buffer_length == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_array<char> map_buffer_chars(new char[map_buffer_length]);
|
if (memory_buffer[map_buffer_length - 1] == '\n') {
|
||||||
if (map_buffer_chars == NULL) {
|
memory_buffer[map_buffer_length - 1] = '\0';
|
||||||
BPLOG(ERROR) << "Memory allocation of " << map_buffer_length <<
|
|
||||||
" bytes failed";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(map_buffer_chars.get(), map_buffer_c_str, map_buffer_length);
|
|
||||||
|
|
||||||
if (map_buffer_chars[map_buffer_length - 1] == '\n') {
|
|
||||||
map_buffer_chars[map_buffer_length - 1] = '\0';
|
|
||||||
}
|
|
||||||
char *buffer;
|
char *buffer;
|
||||||
buffer = strtok_r(map_buffer_chars.get(), "\r\n", &save_ptr);
|
buffer = strtok_r(memory_buffer, "\r\n", &save_ptr);
|
||||||
|
|
||||||
while (buffer != NULL) {
|
while (buffer != NULL) {
|
||||||
++line_number;
|
++line_number;
|
||||||
|
@ -413,68 +146,11 @@ bool BasicSourceLineResolver::Module::LoadMapFromBuffer(
|
||||||
cur_func->lines.StoreRange(line->address, line->size,
|
cur_func->lines.StoreRange(line->address, line->size,
|
||||||
linked_ptr<Line>(line));
|
linked_ptr<Line>(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = strtok_r(NULL, "\r\n", &save_ptr);
|
buffer = strtok_r(NULL, "\r\n", &save_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) {
|
|
||||||
struct stat buf;
|
|
||||||
int error_code = stat(map_file.c_str(), &buf);
|
|
||||||
if (error_code == -1) {
|
|
||||||
string error_string;
|
|
||||||
int error_code = ErrnoString(&error_string);
|
|
||||||
BPLOG(ERROR) << "Could not open " << map_file <<
|
|
||||||
", error " << error_code << ": " << error_string;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t file_size = buf.st_size;
|
|
||||||
|
|
||||||
// Allocate memory for file contents, plus a null terminator
|
|
||||||
// since we'll use strtok() on the contents.
|
|
||||||
char *file_buffer = new char[sizeof(char)*file_size + 1];
|
|
||||||
|
|
||||||
if (file_buffer == NULL) {
|
|
||||||
BPLOG(ERROR) << "Could not allocate memory for " << map_file;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BPLOG(INFO) << "Opening " << map_file;
|
|
||||||
|
|
||||||
FILE *f = fopen(map_file.c_str(), "rt");
|
|
||||||
if (!f) {
|
|
||||||
string error_string;
|
|
||||||
int error_code = ErrnoString(&error_string);
|
|
||||||
BPLOG(ERROR) << "Could not open " << map_file <<
|
|
||||||
", error " << error_code << ": " << error_string;
|
|
||||||
delete [] file_buffer;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoFileCloser closer(f);
|
|
||||||
|
|
||||||
int items_read = 0;
|
|
||||||
|
|
||||||
items_read = fread(file_buffer, 1, file_size, f);
|
|
||||||
|
|
||||||
if (items_read != file_size) {
|
|
||||||
string error_string;
|
|
||||||
int error_code = ErrnoString(&error_string);
|
|
||||||
BPLOG(ERROR) << "Could not slurp " << map_file <<
|
|
||||||
", error " << error_code << ": " << error_string;
|
|
||||||
delete [] file_buffer;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file_buffer[file_size] = '\0';
|
|
||||||
string map_buffer(file_buffer);
|
|
||||||
delete [] file_buffer;
|
|
||||||
|
|
||||||
return LoadMapFromBuffer(map_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
|
void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
|
||||||
MemAddr address = frame->instruction - frame->module->base_address();
|
MemAddr address = frame->instruction - frame->module->base_address();
|
||||||
|
|
||||||
|
@ -543,7 +219,7 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
|
||||||
linked_ptr<Function> function;
|
linked_ptr<Function> function;
|
||||||
MemAddr function_base, function_size;
|
MemAddr function_base, function_size;
|
||||||
if (functions_.RetrieveNearestRange(address, &function,
|
if (functions_.RetrieveNearestRange(address, &function,
|
||||||
&function_base, &function_size) &&
|
&function_base, &function_size) &&
|
||||||
address >= function_base && address - function_base < function_size) {
|
address >= function_base && address - function_base < function_size) {
|
||||||
result->parameter_size = function->parameter_size;
|
result->parameter_size = function->parameter_size;
|
||||||
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
|
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
|
||||||
|
@ -558,7 +234,7 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
|
||||||
(!function.get() || public_address > function_base)) {
|
(!function.get() || public_address > function_base)) {
|
||||||
result->parameter_size = public_symbol->parameter_size;
|
result->parameter_size = public_symbol->parameter_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,13 +272,6 @@ CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
|
||||||
return rules.release();
|
return rules.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BasicSourceLineResolver::Module::ParseCFIRuleSet(
|
|
||||||
const string &rule_set, CFIFrameInfo *frame_info) const {
|
|
||||||
CFIFrameInfoParseHandler handler(frame_info);
|
|
||||||
CFIRuleParser parser(&handler);
|
|
||||||
return parser.Parse(rule_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
|
bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
|
||||||
// FILE <id> <filename>
|
// FILE <id> <filename>
|
||||||
file_line += 5; // skip prefix
|
file_line += 5; // skip prefix
|
||||||
|
@ -762,7 +431,7 @@ bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
|
||||||
// This record has the form "STACK INIT <address> <size> <rules...>".
|
// This record has the form "STACK INIT <address> <size> <rules...>".
|
||||||
char *address_field = strtok_r(NULL, " \r\n", &cursor);
|
char *address_field = strtok_r(NULL, " \r\n", &cursor);
|
||||||
if (!address_field) return false;
|
if (!address_field) return false;
|
||||||
|
|
||||||
char *size_field = strtok_r(NULL, " \r\n", &cursor);
|
char *size_field = strtok_r(NULL, " \r\n", &cursor);
|
||||||
if (!size_field) return false;
|
if (!size_field) return false;
|
||||||
|
|
||||||
|
@ -784,9 +453,4 @@ bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BasicSourceLineResolver::CompareString::operator()(
|
|
||||||
const string &s1, const string &s2) const {
|
|
||||||
return strcmp(s1.c_str(), s2.c_str()) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
159
src/processor/basic_source_line_resolver_types.h
Normal file
159
src/processor/basic_source_line_resolver_types.h
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// basic_source_line_types.h: definition of nested classes/structs in
|
||||||
|
// BasicSourceLineResolver. It moves the definitions out of
|
||||||
|
// basic_source_line_resolver.cc, so that other classes could have access
|
||||||
|
// to these private nested types without including basic_source_line_resolver.cc
|
||||||
|
//
|
||||||
|
// Author: Siyang Xie (lambxsy@google.com)
|
||||||
|
|
||||||
|
#ifndef PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
|
||||||
|
#define PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||||
|
#include "processor/source_line_resolver_base_types.h"
|
||||||
|
|
||||||
|
#include "processor/address_map-inl.h"
|
||||||
|
#include "processor/range_map-inl.h"
|
||||||
|
#include "processor/contained_range_map-inl.h"
|
||||||
|
|
||||||
|
#include "processor/linked_ptr.h"
|
||||||
|
#include "processor/scoped_ptr.h"
|
||||||
|
#include "google_breakpad/processor/stack_frame.h"
|
||||||
|
#include "processor/cfi_frame_info.h"
|
||||||
|
#include "processor/windows_frame_info.h"
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
struct
|
||||||
|
BasicSourceLineResolver::Function : public SourceLineResolverBase::Function {
|
||||||
|
Function(const string &function_name,
|
||||||
|
MemAddr function_address,
|
||||||
|
MemAddr code_size,
|
||||||
|
int set_parameter_size) : Base(function_name,
|
||||||
|
function_address,
|
||||||
|
code_size,
|
||||||
|
set_parameter_size),
|
||||||
|
lines() { }
|
||||||
|
RangeMap< MemAddr, linked_ptr<Line> > lines;
|
||||||
|
private:
|
||||||
|
typedef SourceLineResolverBase::Function Base;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module {
|
||||||
|
public:
|
||||||
|
explicit Module(const string &name) : name_(name) { }
|
||||||
|
virtual ~Module() { }
|
||||||
|
|
||||||
|
// Loads a map from the given buffer in char* type.
|
||||||
|
// Does NOT have ownership of memory_buffer.
|
||||||
|
virtual bool LoadMapFromMemory(char *memory_buffer);
|
||||||
|
|
||||||
|
// Looks up the given relative address, and fills the StackFrame struct
|
||||||
|
// with the result.
|
||||||
|
virtual void LookupAddress(StackFrame *frame) const;
|
||||||
|
|
||||||
|
// 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 declarations.
|
||||||
|
friend class BasicSourceLineResolver;
|
||||||
|
|
||||||
|
typedef std::map<int, string> FileMap;
|
||||||
|
|
||||||
|
// Parses a file declaration
|
||||||
|
bool ParseFile(char *file_line);
|
||||||
|
|
||||||
|
// Parses a function declaration, returning a new Function object.
|
||||||
|
Function* ParseFunction(char *function_line);
|
||||||
|
|
||||||
|
// Parses a line declaration, returning a new Line object.
|
||||||
|
Line* ParseLine(char *line_line);
|
||||||
|
|
||||||
|
// Parses a PUBLIC symbol declaration, storing it in public_symbols_.
|
||||||
|
// Returns false if an error occurs.
|
||||||
|
bool ParsePublicSymbol(char *public_line);
|
||||||
|
|
||||||
|
// Parses a STACK WIN or STACK CFI frame info declaration, storing
|
||||||
|
// it in the appropriate table.
|
||||||
|
bool ParseStackInfo(char *stack_info_line);
|
||||||
|
|
||||||
|
// Parses a STACK CFI record, storing it in cfi_frame_info_.
|
||||||
|
bool ParseCFIFrameInfo(char *stack_info_line);
|
||||||
|
|
||||||
|
string name_;
|
||||||
|
FileMap files_;
|
||||||
|
RangeMap< MemAddr, linked_ptr<Function> > functions_;
|
||||||
|
AddressMap< MemAddr, linked_ptr<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.
|
||||||
|
ContainedRangeMap< MemAddr, linked_ptr<WindowsFrameInfo> >
|
||||||
|
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.
|
||||||
|
RangeMap<MemAddr, string> 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).
|
||||||
|
std::map<MemAddr, string> cfi_delta_rules_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
|
|
@ -93,6 +93,11 @@ class TestSymbolSupplier : public SymbolSupplier {
|
||||||
string *symbol_file,
|
string *symbol_file,
|
||||||
string *symbol_data);
|
string *symbol_data);
|
||||||
|
|
||||||
|
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data);
|
||||||
|
|
||||||
// When set to true, causes the SymbolSupplier to return INTERRUPT
|
// When set to true, causes the SymbolSupplier to return INTERRUPT
|
||||||
void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
|
void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
|
||||||
|
|
||||||
|
@ -112,6 +117,14 @@ SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
||||||
return NOT_FOUND;
|
return NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData(
|
||||||
|
const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data) {
|
||||||
|
return GetSymbolFile(module, system_info, symbol_file);
|
||||||
|
}
|
||||||
|
|
||||||
SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
||||||
const CodeModule *module,
|
const CodeModule *module,
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
|
|
|
@ -113,6 +113,11 @@ class TestSymbolSupplier : public SymbolSupplier {
|
||||||
string *symbol_file,
|
string *symbol_file,
|
||||||
string *symbol_data);
|
string *symbol_data);
|
||||||
|
|
||||||
|
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data);
|
||||||
|
|
||||||
// When set to true, causes the SymbolSupplier to return INTERRUPT
|
// When set to true, causes the SymbolSupplier to return INTERRUPT
|
||||||
void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
|
void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
|
||||||
|
|
||||||
|
@ -164,6 +169,25 @@ SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData(
|
||||||
|
const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data) {
|
||||||
|
string symbol_data_string;
|
||||||
|
SymbolSupplier::SymbolResult s = GetSymbolFile(module,
|
||||||
|
system_info,
|
||||||
|
symbol_file,
|
||||||
|
&symbol_data_string);
|
||||||
|
if (s == FOUND) {
|
||||||
|
unsigned int size = symbol_data_string.size() + 1;
|
||||||
|
*symbol_data = reinterpret_cast<char*>(operator new(size));
|
||||||
|
strcpy(*symbol_data, symbol_data_string.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
// A mock symbol supplier that always returns NOT_FOUND; one current
|
// A mock symbol supplier that always returns NOT_FOUND; one current
|
||||||
// use for testing the processor's caching of symbol lookups.
|
// use for testing the processor's caching of symbol lookups.
|
||||||
class MockSymbolSupplier : public SymbolSupplier {
|
class MockSymbolSupplier : public SymbolSupplier {
|
||||||
|
@ -176,6 +200,10 @@ class MockSymbolSupplier : public SymbolSupplier {
|
||||||
const SystemInfo*,
|
const SystemInfo*,
|
||||||
string*,
|
string*,
|
||||||
string*));
|
string*));
|
||||||
|
MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule*,
|
||||||
|
const SystemInfo*,
|
||||||
|
string*,
|
||||||
|
char**));
|
||||||
};
|
};
|
||||||
|
|
||||||
class MinidumpProcessorTest : public ::testing::Test {
|
class MinidumpProcessorTest : public ::testing::Test {
|
||||||
|
@ -217,11 +245,11 @@ TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) {
|
||||||
string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
|
string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
|
||||||
"/src/processor/testdata/minidump2.dmp";
|
"/src/processor/testdata/minidump2.dmp";
|
||||||
ProcessState state;
|
ProcessState state;
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(
|
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||||
Property(&google_breakpad::CodeModule::code_file,
|
Property(&google_breakpad::CodeModule::code_file,
|
||||||
"c:\\test_app.exe"),
|
"c:\\test_app.exe"),
|
||||||
_, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
|
_, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(
|
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||||
Property(&google_breakpad::CodeModule::code_file,
|
Property(&google_breakpad::CodeModule::code_file,
|
||||||
Ne("c:\\test_app.exe")),
|
Ne("c:\\test_app.exe")),
|
||||||
_, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
|
_, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
|
||||||
|
@ -232,11 +260,11 @@ TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) {
|
||||||
|
|
||||||
// We need to verify that across minidumps, the processor will refetch
|
// We need to verify that across minidumps, the processor will refetch
|
||||||
// symbol files, even with the same symbol supplier.
|
// symbol files, even with the same symbol supplier.
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(
|
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||||
Property(&google_breakpad::CodeModule::code_file,
|
Property(&google_breakpad::CodeModule::code_file,
|
||||||
"c:\\test_app.exe"),
|
"c:\\test_app.exe"),
|
||||||
_, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
|
_, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(
|
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||||
Property(&google_breakpad::CodeModule::code_file,
|
Property(&google_breakpad::CodeModule::code_file,
|
||||||
Ne("c:\\test_app.exe")),
|
Ne("c:\\test_app.exe")),
|
||||||
_, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
|
_, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
|
||||||
|
|
62
src/processor/module_factory.h
Normal file
62
src/processor/module_factory.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// 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_factory.h: ModuleFactory a factory that provides
|
||||||
|
// an interface for creating a Module and deferring instantiation to subclasses
|
||||||
|
// BasicModuleFactory and FastModuleFactory.
|
||||||
|
|
||||||
|
// Author: Siyang Xie (lambxsy@google.com)
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
class ModuleFactory {
|
||||||
|
public:
|
||||||
|
virtual ~ModuleFactory() { };
|
||||||
|
virtual SourceLineResolverBase::Module*
|
||||||
|
CreateModule(const string &name) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BasicModuleFactory : public ModuleFactory {
|
||||||
|
public:
|
||||||
|
virtual ~BasicModuleFactory() { }
|
||||||
|
virtual BasicSourceLineResolver::Module*
|
||||||
|
CreateModule(const string &name) const {
|
||||||
|
return new BasicSourceLineResolver::Module(name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // PROCESSOR_MODULE_FACTORY_H__
|
|
@ -97,6 +97,13 @@ bool NetworkSourceLineResolver::LoadModuleUsingMapBuffer(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetworkSourceLineResolver::LoadModuleUsingMemoryBuffer(
|
||||||
|
const CodeModule *module,
|
||||||
|
char *memory_buffer) {
|
||||||
|
// see above
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkSourceLineResolver::UnloadModule(const CodeModule *module) {
|
void NetworkSourceLineResolver::UnloadModule(const CodeModule *module) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
@ -331,6 +338,18 @@ NetworkSourceLineResolver::GetSymbolFile(const CodeModule *module,
|
||||||
return GetSymbolFile(module, system_info, symbol_file);
|
return GetSymbolFile(module, system_info, symbol_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolSupplier::SymbolResult
|
||||||
|
NetworkSourceLineResolver::GetCStringSymbolData(
|
||||||
|
const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data) {
|
||||||
|
if (symbol_data)
|
||||||
|
delete *symbol_data;
|
||||||
|
|
||||||
|
return GetSymbolFile(module, system_info, symbol_file);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetworkSourceLineResolver::SendMessageGetResponse(
|
bool NetworkSourceLineResolver::SendMessageGetResponse(
|
||||||
const binarystream &message,
|
const binarystream &message,
|
||||||
binarystream &response) {
|
binarystream &response) {
|
||||||
|
|
|
@ -89,6 +89,10 @@ public:
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
string *symbol_file,
|
string *symbol_file,
|
||||||
string *symbol_data));
|
string *symbol_data));
|
||||||
|
MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data));
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockSourceLineResolver : public SourceLineResolverInterface {
|
class MockSourceLineResolver : public SourceLineResolverInterface {
|
||||||
|
@ -100,6 +104,8 @@ class MockSourceLineResolver : public SourceLineResolverInterface {
|
||||||
const string &map_file));
|
const string &map_file));
|
||||||
MOCK_METHOD2(LoadModuleUsingMapBuffer, bool(const CodeModule *module,
|
MOCK_METHOD2(LoadModuleUsingMapBuffer, bool(const CodeModule *module,
|
||||||
const string &map_buffer));
|
const string &map_buffer));
|
||||||
|
MOCK_METHOD2(LoadModuleUsingMemoryBuffer, bool(const CodeModule *module,
|
||||||
|
char *memory_buffer));
|
||||||
MOCK_METHOD1(UnloadModule, void(const CodeModule *module));
|
MOCK_METHOD1(UnloadModule, void(const CodeModule *module));
|
||||||
MOCK_METHOD1(HasModule, bool(const CodeModule *module));
|
MOCK_METHOD1(HasModule, bool(const CodeModule *module));
|
||||||
MOCK_METHOD1(FillSourceLineInfo, void(StackFrame *frame));
|
MOCK_METHOD1(FillSourceLineInfo, void(StackFrame *frame));
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "processor/simple_symbol_supplier.h"
|
#include "processor/simple_symbol_supplier.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -93,6 +94,26 @@ SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile(
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetCStringSymbolData(
|
||||||
|
const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data) {
|
||||||
|
assert(symbol_data);
|
||||||
|
|
||||||
|
string symbol_data_string;
|
||||||
|
SymbolSupplier::SymbolResult s =
|
||||||
|
GetSymbolFile(module, system_info, symbol_file, &symbol_data_string);
|
||||||
|
|
||||||
|
if (s == FOUND) {
|
||||||
|
unsigned int size = symbol_data_string.size() + 1;
|
||||||
|
*symbol_data = reinterpret_cast<char*>(operator new(size));
|
||||||
|
memcpy(*symbol_data, symbol_data_string.c_str(), size - 1);
|
||||||
|
(*symbol_data)[size - 1] = '\0';
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot(
|
SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot(
|
||||||
const CodeModule *module, const SystemInfo *system_info,
|
const CodeModule *module, const SystemInfo *system_info,
|
||||||
const string &root_path, string *symbol_file) {
|
const string &root_path, string *symbol_file) {
|
||||||
|
|
|
@ -110,6 +110,12 @@ class SimpleSymbolSupplier : public SymbolSupplier {
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
string *symbol_file,
|
string *symbol_file,
|
||||||
string *symbol_data);
|
string *symbol_data);
|
||||||
|
|
||||||
|
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
string *symbol_file,
|
||||||
|
char **symbol_data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module,
|
SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module,
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
|
|
283
src/processor/source_line_resolver_base.cc
Normal file
283
src/processor/source_line_resolver_base.cc
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// source_line_resolver_base.cc: Implementation of SourceLineResolverBase.
|
||||||
|
//
|
||||||
|
// See source_line_resolver_base.h and source_line_resolver_base_types.h for
|
||||||
|
// more documentation.
|
||||||
|
//
|
||||||
|
// Author: Siyang Xie (lambxsy@google.com)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||||
|
#include "processor/source_line_resolver_base_types.h"
|
||||||
|
#include "processor/module_factory.h"
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
using std::make_pair;
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
SourceLineResolverBase::SourceLineResolverBase(
|
||||||
|
ModuleFactory *module_factory)
|
||||||
|
: modules_(new ModuleMap),
|
||||||
|
module_factory_(module_factory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceLineResolverBase::~SourceLineResolverBase() {
|
||||||
|
ModuleMap::iterator it;
|
||||||
|
// Iterate through ModuleMap and delete all loaded modules.
|
||||||
|
for (it = modules_->begin(); it != modules_->end(); ++it) {
|
||||||
|
// Delete individual module.
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
// Delete the map of modules.
|
||||||
|
delete modules_;
|
||||||
|
delete module_factory_;
|
||||||
|
|
||||||
|
// Helper method to be specified by subclasses.
|
||||||
|
ClearLocalMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods to be specified by subclasses.
|
||||||
|
void SourceLineResolverBase::StoreDataBeforeLoad(const CodeModule *module,
|
||||||
|
char *symbol_data) { }
|
||||||
|
void SourceLineResolverBase::DeleteDataAfterLoad(char *symbol_data) { }
|
||||||
|
void SourceLineResolverBase::DeleteDataUnload(const CodeModule *module) { }
|
||||||
|
void SourceLineResolverBase::ClearLocalMemory() { }
|
||||||
|
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::ReadSymbolFile(char **symbol_data,
|
||||||
|
const string &map_file) {
|
||||||
|
if (symbol_data == NULL) {
|
||||||
|
BPLOG(ERROR) << "Could not Read file into Null memory pointer";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat buf;
|
||||||
|
int error_code = stat(map_file.c_str(), &buf);
|
||||||
|
if (error_code == -1) {
|
||||||
|
string error_string;
|
||||||
|
int error_code = ErrnoString(&error_string);
|
||||||
|
BPLOG(ERROR) << "Could not open " << map_file <<
|
||||||
|
", error " << error_code << ": " << error_string;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t file_size = buf.st_size;
|
||||||
|
|
||||||
|
// Allocate memory for file contents, plus a null terminator
|
||||||
|
// since we may use strtok() on the contents.
|
||||||
|
*symbol_data = reinterpret_cast<char*>(operator new(file_size + 1));
|
||||||
|
|
||||||
|
if (*symbol_data == NULL) {
|
||||||
|
BPLOG(ERROR) << "Could not allocate memory for " << map_file;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Opening " << map_file;
|
||||||
|
|
||||||
|
FILE *f = fopen(map_file.c_str(), "rt");
|
||||||
|
if (!f) {
|
||||||
|
string error_string;
|
||||||
|
int error_code = ErrnoString(&error_string);
|
||||||
|
BPLOG(ERROR) << "Could not open " << map_file <<
|
||||||
|
", error " << error_code << ": " << error_string;
|
||||||
|
delete (*symbol_data);
|
||||||
|
*symbol_data = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoFileCloser closer(f);
|
||||||
|
|
||||||
|
int items_read = 0;
|
||||||
|
|
||||||
|
items_read = fread(*symbol_data, 1, file_size, f);
|
||||||
|
|
||||||
|
if (items_read != file_size) {
|
||||||
|
string error_string;
|
||||||
|
int error_code = ErrnoString(&error_string);
|
||||||
|
BPLOG(ERROR) << "Could not slurp " << map_file <<
|
||||||
|
", error " << error_code << ": " << error_string;
|
||||||
|
delete (*symbol_data);
|
||||||
|
*symbol_data = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*symbol_data)[file_size] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::LoadModule(const CodeModule *module,
|
||||||
|
const string &map_file) {
|
||||||
|
if (module == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Make sure we don't already have a module with the given name.
|
||||||
|
if (modules_->find(module->code_file()) != modules_->end()) {
|
||||||
|
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
||||||
|
<< " already loaded";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
||||||
|
<< " from " << map_file;
|
||||||
|
|
||||||
|
char *memory_buffer;
|
||||||
|
if (!ReadSymbolFile(&memory_buffer, map_file))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Read symbol file " << map_file << " succeeded";
|
||||||
|
|
||||||
|
// Invoke helper method, let the concrete subclass decides its own action.
|
||||||
|
StoreDataBeforeLoad(module, memory_buffer);
|
||||||
|
|
||||||
|
return LoadModuleUsingMemoryBuffer(module, memory_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::LoadModuleUsingMapBuffer(
|
||||||
|
const CodeModule *module, const string &map_buffer) {
|
||||||
|
char *memory_buffer = reinterpret_cast<char*>(
|
||||||
|
operator new(map_buffer.size() + 1));
|
||||||
|
if (memory_buffer == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Can't use strcpy, as the data may contain '\0's before the end.
|
||||||
|
memcpy(memory_buffer, map_buffer.c_str(), map_buffer.size());
|
||||||
|
memory_buffer[map_buffer.size()] = '\0';
|
||||||
|
|
||||||
|
// Invoke helper method, let the concrete subclass decides its own action.
|
||||||
|
StoreDataBeforeLoad(module, memory_buffer);
|
||||||
|
|
||||||
|
return LoadModuleUsingMemoryBuffer(module, memory_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::LoadModuleUsingMemoryBuffer(
|
||||||
|
const CodeModule *module, char *memory_buffer) {
|
||||||
|
if (!module) {
|
||||||
|
// Invoke helper method, let the concrete subclass decides its own action.
|
||||||
|
DeleteDataAfterLoad(memory_buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we don't already have a module with the given name.
|
||||||
|
if (modules_->find(module->code_file()) != modules_->end()) {
|
||||||
|
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
||||||
|
<< " already loaded";
|
||||||
|
DeleteDataAfterLoad(memory_buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
||||||
|
<< " from buffer";
|
||||||
|
|
||||||
|
Module *basic_module = module_factory_->CreateModule(module->code_file());
|
||||||
|
|
||||||
|
// Ownership of memory is NOT transfered to Module::LoadMapFromMemory().
|
||||||
|
if (!basic_module->LoadMapFromMemory(memory_buffer)) {
|
||||||
|
delete basic_module;
|
||||||
|
DeleteDataAfterLoad(memory_buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules_->insert(make_pair(module->code_file(), basic_module));
|
||||||
|
DeleteDataAfterLoad(memory_buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceLineResolverBase::UnloadModule(const CodeModule *code_module) {
|
||||||
|
if (!code_module)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModuleMap::iterator iter = modules_->find(code_module->code_file());
|
||||||
|
if (iter != modules_->end()) {
|
||||||
|
Module *symbol_module = iter->second;
|
||||||
|
delete symbol_module;
|
||||||
|
modules_->erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteDataUnload(code_module);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::HasModule(const CodeModule *module) {
|
||||||
|
if (!module)
|
||||||
|
return false;
|
||||||
|
return modules_->find(module->code_file()) != modules_->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceLineResolverBase::FillSourceLineInfo(StackFrame *frame) {
|
||||||
|
if (frame->module) {
|
||||||
|
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||||
|
if (it != modules_->end()) {
|
||||||
|
it->second->LookupAddress(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsFrameInfo *SourceLineResolverBase::FindWindowsFrameInfo(
|
||||||
|
const StackFrame *frame) {
|
||||||
|
if (frame->module) {
|
||||||
|
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||||
|
if (it != modules_->end()) {
|
||||||
|
return it->second->FindWindowsFrameInfo(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFIFrameInfo *SourceLineResolverBase::FindCFIFrameInfo(
|
||||||
|
const StackFrame *frame) {
|
||||||
|
if (frame->module) {
|
||||||
|
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||||
|
if (it != modules_->end()) {
|
||||||
|
return it->second->FindCFIFrameInfo(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::CompareString::operator()(
|
||||||
|
const string &s1, const string &s2) const {
|
||||||
|
return strcmp(s1.c_str(), s2.c_str()) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceLineResolverBase::Module::ParseCFIRuleSet(
|
||||||
|
const string &rule_set, CFIFrameInfo *frame_info) const {
|
||||||
|
CFIFrameInfoParseHandler handler(frame_info);
|
||||||
|
CFIRuleParser parser(&handler);
|
||||||
|
return parser.Parse(rule_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
149
src/processor/source_line_resolver_base_types.h
Normal file
149
src/processor/source_line_resolver_base_types.h
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// source_line_resolver_base_types.h: definition of nested classes/structs in
|
||||||
|
// SourceLineResolverBase. It moves the definitions out of
|
||||||
|
// source_line_resolver_base.cc, so that other classes may have access
|
||||||
|
// to these private nested types without including source_line_resolver_base.cc
|
||||||
|
// In addition, Module is defined as a pure abstract class to be implemented by
|
||||||
|
// each concrete source line resolver class.
|
||||||
|
//
|
||||||
|
// See source_line_resolver_base.h for more documentation.
|
||||||
|
//
|
||||||
|
// Author: Siyang Xie (lambxsy@google.com)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||||
|
#include "google_breakpad/processor/stack_frame.h"
|
||||||
|
#include "processor/cfi_frame_info.h"
|
||||||
|
#include "processor/windows_frame_info.h"
|
||||||
|
|
||||||
|
#ifndef PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
|
||||||
|
#define PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
class SourceLineResolverBase::AutoFileCloser {
|
||||||
|
public:
|
||||||
|
explicit AutoFileCloser(FILE *file) : file_(file) {}
|
||||||
|
~AutoFileCloser() {
|
||||||
|
if (file_)
|
||||||
|
fclose(file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE *file_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SourceLineResolverBase::Line {
|
||||||
|
Line() { }
|
||||||
|
Line(MemAddr addr, MemAddr code_size, int file_id, int source_line)
|
||||||
|
: address(addr)
|
||||||
|
, size(code_size)
|
||||||
|
, source_file_id(file_id)
|
||||||
|
, line(source_line) { }
|
||||||
|
|
||||||
|
MemAddr address;
|
||||||
|
MemAddr size;
|
||||||
|
int32_t source_file_id;
|
||||||
|
int32_t line;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SourceLineResolverBase::Function {
|
||||||
|
Function() { }
|
||||||
|
Function(const string &function_name,
|
||||||
|
MemAddr function_address,
|
||||||
|
MemAddr code_size,
|
||||||
|
int set_parameter_size)
|
||||||
|
: name(function_name), address(function_address), size(code_size),
|
||||||
|
parameter_size(set_parameter_size) { }
|
||||||
|
|
||||||
|
string name;
|
||||||
|
MemAddr address;
|
||||||
|
MemAddr size;
|
||||||
|
|
||||||
|
// The size of parameters passed to this function on the stack.
|
||||||
|
int32_t parameter_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SourceLineResolverBase::PublicSymbol {
|
||||||
|
PublicSymbol() { }
|
||||||
|
PublicSymbol(const string& set_name,
|
||||||
|
MemAddr set_address,
|
||||||
|
int set_parameter_size)
|
||||||
|
: name(set_name),
|
||||||
|
address(set_address),
|
||||||
|
parameter_size(set_parameter_size) {}
|
||||||
|
|
||||||
|
string name;
|
||||||
|
MemAddr address;
|
||||||
|
|
||||||
|
// If the public symbol is used as a function entry point, parameter_size
|
||||||
|
// is set to the size of the parameters passed to the funciton on the
|
||||||
|
// stack, if known.
|
||||||
|
int32_t parameter_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SourceLineResolverBase::Module {
|
||||||
|
public:
|
||||||
|
virtual ~Module() { };
|
||||||
|
// Loads a map from the given buffer in char* type.
|
||||||
|
// Does NOT take ownership of memory_buffer (the caller, source line resolver,
|
||||||
|
// is the owner of memory_buffer).
|
||||||
|
virtual bool LoadMapFromMemory(char *memory_buffer) = 0;
|
||||||
|
|
||||||
|
// Looks up the given relative address, and fills the StackFrame struct
|
||||||
|
// with the result.
|
||||||
|
virtual void LookupAddress(StackFrame *frame) const = 0;
|
||||||
|
|
||||||
|
// 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 = 0;
|
||||||
|
|
||||||
|
// 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 = 0;
|
||||||
|
protected:
|
||||||
|
virtual bool ParseCFIRuleSet(const string &rule_set,
|
||||||
|
CFIFrameInfo *frame_info) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
|
|
@ -97,15 +97,18 @@ bool Stackwalker::Walk(CallStack *stack) {
|
||||||
no_symbol_modules_.find(
|
no_symbol_modules_.find(
|
||||||
module->code_file()) == no_symbol_modules_.end() &&
|
module->code_file()) == no_symbol_modules_.end() &&
|
||||||
supplier_) {
|
supplier_) {
|
||||||
string symbol_data, symbol_file;
|
string symbol_file;
|
||||||
|
char *symbol_data;
|
||||||
SymbolSupplier::SymbolResult symbol_result =
|
SymbolSupplier::SymbolResult symbol_result =
|
||||||
supplier_->GetSymbolFile(module, system_info_,
|
supplier_->GetCStringSymbolData(module,
|
||||||
&symbol_file, &symbol_data);
|
system_info_,
|
||||||
|
&symbol_file,
|
||||||
|
&symbol_data);
|
||||||
|
|
||||||
switch (symbol_result) {
|
switch (symbol_result) {
|
||||||
case SymbolSupplier::FOUND:
|
case SymbolSupplier::FOUND:
|
||||||
resolver_->LoadModuleUsingMapBuffer(frame->module,
|
resolver_->LoadModuleUsingMemoryBuffer(frame->module,
|
||||||
symbol_data);
|
symbol_data);
|
||||||
break;
|
break;
|
||||||
case SymbolSupplier::NOT_FOUND:
|
case SymbolSupplier::NOT_FOUND:
|
||||||
no_symbol_modules_.insert(module->code_file());
|
no_symbol_modules_.insert(module->code_file());
|
||||||
|
@ -207,13 +210,14 @@ bool Stackwalker::InstructionAddressSeemsValid(u_int64_t address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resolver_->HasModule(module)) {
|
if (!resolver_->HasModule(module)) {
|
||||||
string symbol_data, symbol_file;
|
string symbol_file;
|
||||||
|
char *symbol_data;
|
||||||
SymbolSupplier::SymbolResult symbol_result =
|
SymbolSupplier::SymbolResult symbol_result =
|
||||||
supplier_->GetSymbolFile(module, system_info_,
|
supplier_->GetCStringSymbolData(module, system_info_,
|
||||||
&symbol_file, &symbol_data);
|
&symbol_file, &symbol_data);
|
||||||
|
|
||||||
if (symbol_result != SymbolSupplier::FOUND ||
|
if (symbol_result != SymbolSupplier::FOUND ||
|
||||||
!resolver_->LoadModuleUsingMapBuffer(module,
|
!resolver_->LoadModuleUsingMemoryBuffer(module,
|
||||||
symbol_data)) {
|
symbol_data)) {
|
||||||
// we don't have symbols, but we're inside a loaded module
|
// we don't have symbols, but we're inside a loaded module
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -85,15 +85,18 @@ class StackwalkerAMD64Fixture {
|
||||||
|
|
||||||
// By default, none of the modules have symbol info; call
|
// By default, none of the modules have symbol info; call
|
||||||
// SetModuleSymbols to override this.
|
// SetModuleSymbols to override this.
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(_, _, _, _))
|
EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
|
||||||
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the Breakpad symbol information that supplier should return for
|
// Set the Breakpad symbol information that supplier should return for
|
||||||
// MODULE to INFO.
|
// MODULE to INFO.
|
||||||
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(module, &system_info, _, _))
|
unsigned int buffer_size = info.size() + 1;
|
||||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(info),
|
char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
|
||||||
|
strcpy(buffer, info.c_str());
|
||||||
|
EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
|
||||||
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
|
||||||
Return(MockSymbolSupplier::FOUND)));
|
Return(MockSymbolSupplier::FOUND)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,15 +87,18 @@ class StackwalkerARMFixture {
|
||||||
|
|
||||||
// By default, none of the modules have symbol info; call
|
// By default, none of the modules have symbol info; call
|
||||||
// SetModuleSymbols to override this.
|
// SetModuleSymbols to override this.
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(_, _, _, _))
|
EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
|
||||||
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the Breakpad symbol information that supplier should return for
|
// Set the Breakpad symbol information that supplier should return for
|
||||||
// MODULE to INFO.
|
// MODULE to INFO.
|
||||||
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(module, &system_info, _, _))
|
unsigned int buffer_size = info.size() + 1;
|
||||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(info),
|
char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
|
||||||
|
strcpy(buffer, info.c_str());
|
||||||
|
EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
|
||||||
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
|
||||||
Return(MockSymbolSupplier::FOUND)));
|
Return(MockSymbolSupplier::FOUND)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,10 @@ class MockSymbolSupplier: public google_breakpad::SymbolSupplier {
|
||||||
const SystemInfo *system_info,
|
const SystemInfo *system_info,
|
||||||
std::string *symbol_file,
|
std::string *symbol_file,
|
||||||
std::string *symbol_data));
|
std::string *symbol_data));
|
||||||
|
MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module,
|
||||||
|
const SystemInfo *system_info,
|
||||||
|
std::string *symbol_file,
|
||||||
|
char **symbol_data));
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
|
#endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
|
||||||
|
|
|
@ -86,15 +86,18 @@ class StackwalkerX86Fixture {
|
||||||
|
|
||||||
// By default, none of the modules have symbol info; call
|
// By default, none of the modules have symbol info; call
|
||||||
// SetModuleSymbols to override this.
|
// SetModuleSymbols to override this.
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(_, _, _, _))
|
EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
|
||||||
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the Breakpad symbol information that supplier should return for
|
// Set the Breakpad symbol information that supplier should return for
|
||||||
// MODULE to INFO.
|
// MODULE to INFO.
|
||||||
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
||||||
EXPECT_CALL(supplier, GetSymbolFile(module, &system_info, _, _))
|
unsigned int buffer_size = info.size() + 1;
|
||||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(info),
|
char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
|
||||||
|
strcpy(buffer, info.c_str());
|
||||||
|
EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
|
||||||
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
|
||||||
Return(MockSymbolSupplier::FOUND)));
|
Return(MockSymbolSupplier::FOUND)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#define PROCESSOR_WINDOWS_FRAME_INFO_H__
|
#define PROCESSOR_WINDOWS_FRAME_INFO_H__
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue