Compare commits
4 Commits
main
...
processor-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1b114d00ad | ||
![]() |
eeae662157 | ||
![]() |
b8af9814ba | ||
![]() |
37e2d8391e |
16
Makefile.am
16
Makefile.am
@@ -62,6 +62,7 @@ src_libbreakpad_la_SOURCES = \
|
|||||||
src/google_breakpad/processor/minidump_processor.h \
|
src/google_breakpad/processor/minidump_processor.h \
|
||||||
src/google_breakpad/processor/process_state.h \
|
src/google_breakpad/processor/process_state.h \
|
||||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||||
|
src/google_breakpad/processor/source_line_resolver_module_cache_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 \
|
||||||
src/google_breakpad/processor/stackwalker.h \
|
src/google_breakpad/processor/stackwalker.h \
|
||||||
@@ -76,6 +77,8 @@ src_libbreakpad_la_SOURCES = \
|
|||||||
src/processor/call_stack.cc \
|
src/processor/call_stack.cc \
|
||||||
src/processor/contained_range_map-inl.h \
|
src/processor/contained_range_map-inl.h \
|
||||||
src/processor/contained_range_map.h \
|
src/processor/contained_range_map.h \
|
||||||
|
src/processor/disk_module_cache.cc \
|
||||||
|
src/processor/disk_module_cache.h \
|
||||||
src/processor/linked_ptr.h \
|
src/processor/linked_ptr.h \
|
||||||
src/processor/logging.h \
|
src/processor/logging.h \
|
||||||
src/processor/logging.cc \
|
src/processor/logging.cc \
|
||||||
@@ -117,7 +120,8 @@ check_PROGRAMS = \
|
|||||||
src/processor/minidump_processor_unittest \
|
src/processor/minidump_processor_unittest \
|
||||||
src/processor/pathname_stripper_unittest \
|
src/processor/pathname_stripper_unittest \
|
||||||
src/processor/postfix_evaluator_unittest \
|
src/processor/postfix_evaluator_unittest \
|
||||||
src/processor/range_map_unittest
|
src/processor/range_map_unittest \
|
||||||
|
src/processor/module_serialize_unittest
|
||||||
|
|
||||||
if SELFTEST
|
if SELFTEST
|
||||||
check_PROGRAMS += \
|
check_PROGRAMS += \
|
||||||
@@ -185,6 +189,15 @@ src_processor_range_map_unittest_LDADD = \
|
|||||||
src/processor/logging.lo \
|
src/processor/logging.lo \
|
||||||
src/processor/pathname_stripper.lo
|
src/processor/pathname_stripper.lo
|
||||||
|
|
||||||
|
src_processor_module_serialize_unittest_SOURCES = \
|
||||||
|
src/processor/module_serialize_unittest.cc
|
||||||
|
src_processor_module_serialize_unittest_LDADD = \
|
||||||
|
src/processor/basic_code_modules.lo \
|
||||||
|
src/processor/basic_source_line_resolver.lo \
|
||||||
|
src/processor/call_stack.lo \
|
||||||
|
src/processor/logging.lo \
|
||||||
|
src/processor/pathname_stripper.lo
|
||||||
|
|
||||||
src_processor_stackwalker_selftest_SOURCES = \
|
src_processor_stackwalker_selftest_SOURCES = \
|
||||||
src/processor/stackwalker_selftest.cc
|
src/processor/stackwalker_selftest.cc
|
||||||
src_processor_stackwalker_selftest_LDADD = \
|
src_processor_stackwalker_selftest_LDADD = \
|
||||||
@@ -218,6 +231,7 @@ src_processor_minidump_stackwalk_LDADD = \
|
|||||||
src/processor/basic_code_modules.lo \
|
src/processor/basic_code_modules.lo \
|
||||||
src/processor/basic_source_line_resolver.lo \
|
src/processor/basic_source_line_resolver.lo \
|
||||||
src/processor/call_stack.lo \
|
src/processor/call_stack.lo \
|
||||||
|
src/processor/disk_module_cache.lo \
|
||||||
src/processor/logging.lo \
|
src/processor/logging.lo \
|
||||||
src/processor/minidump.lo \
|
src/processor/minidump.lo \
|
||||||
src/processor/minidump_processor.lo \
|
src/processor/minidump_processor.lo \
|
||||||
|
52
Makefile.in
52
Makefile.in
@@ -72,7 +72,9 @@ check_PROGRAMS = src/processor/address_map_unittest$(EXEEXT) \
|
|||||||
src/processor/minidump_processor_unittest$(EXEEXT) \
|
src/processor/minidump_processor_unittest$(EXEEXT) \
|
||||||
src/processor/pathname_stripper_unittest$(EXEEXT) \
|
src/processor/pathname_stripper_unittest$(EXEEXT) \
|
||||||
src/processor/postfix_evaluator_unittest$(EXEEXT) \
|
src/processor/postfix_evaluator_unittest$(EXEEXT) \
|
||||||
src/processor/range_map_unittest$(EXEEXT) $(am__EXEEXT_1)
|
src/processor/range_map_unittest$(EXEEXT) \
|
||||||
|
src/processor/module_serialize_unittest$(EXEEXT) \
|
||||||
|
$(am__EXEEXT_1)
|
||||||
@SELFTEST_TRUE@am__append_1 = \
|
@SELFTEST_TRUE@am__append_1 = \
|
||||||
@SELFTEST_TRUE@ src/processor/stackwalker_selftest
|
@SELFTEST_TRUE@ src/processor/stackwalker_selftest
|
||||||
|
|
||||||
@@ -107,8 +109,9 @@ src_libbreakpad_la_LIBADD =
|
|||||||
am__dirstamp = $(am__leading_dot)dirstamp
|
am__dirstamp = $(am__leading_dot)dirstamp
|
||||||
am_src_libbreakpad_la_OBJECTS = src/processor/basic_code_modules.lo \
|
am_src_libbreakpad_la_OBJECTS = src/processor/basic_code_modules.lo \
|
||||||
src/processor/basic_source_line_resolver.lo \
|
src/processor/basic_source_line_resolver.lo \
|
||||||
src/processor/call_stack.lo src/processor/logging.lo \
|
src/processor/call_stack.lo src/processor/disk_module_cache.lo \
|
||||||
src/processor/minidump.lo src/processor/minidump_processor.lo \
|
src/processor/logging.lo src/processor/minidump.lo \
|
||||||
|
src/processor/minidump_processor.lo \
|
||||||
src/processor/pathname_stripper.lo \
|
src/processor/pathname_stripper.lo \
|
||||||
src/processor/process_state.lo \
|
src/processor/process_state.lo \
|
||||||
src/processor/simple_symbol_supplier.lo \
|
src/processor/simple_symbol_supplier.lo \
|
||||||
@@ -169,8 +172,9 @@ src_processor_minidump_stackwalk_OBJECTS = \
|
|||||||
src_processor_minidump_stackwalk_DEPENDENCIES = \
|
src_processor_minidump_stackwalk_DEPENDENCIES = \
|
||||||
src/processor/basic_code_modules.lo \
|
src/processor/basic_code_modules.lo \
|
||||||
src/processor/basic_source_line_resolver.lo \
|
src/processor/basic_source_line_resolver.lo \
|
||||||
src/processor/call_stack.lo src/processor/logging.lo \
|
src/processor/call_stack.lo src/processor/disk_module_cache.lo \
|
||||||
src/processor/minidump.lo src/processor/minidump_processor.lo \
|
src/processor/logging.lo src/processor/minidump.lo \
|
||||||
|
src/processor/minidump_processor.lo \
|
||||||
src/processor/pathname_stripper.lo \
|
src/processor/pathname_stripper.lo \
|
||||||
src/processor/process_state.lo \
|
src/processor/process_state.lo \
|
||||||
src/processor/simple_symbol_supplier.lo \
|
src/processor/simple_symbol_supplier.lo \
|
||||||
@@ -179,6 +183,15 @@ src_processor_minidump_stackwalk_DEPENDENCIES = \
|
|||||||
src/processor/stackwalker_ppc.lo \
|
src/processor/stackwalker_ppc.lo \
|
||||||
src/processor/stackwalker_sparc.lo \
|
src/processor/stackwalker_sparc.lo \
|
||||||
src/processor/stackwalker_x86.lo
|
src/processor/stackwalker_x86.lo
|
||||||
|
am_src_processor_module_serialize_unittest_OBJECTS = \
|
||||||
|
src/processor/module_serialize_unittest.$(OBJEXT)
|
||||||
|
src_processor_module_serialize_unittest_OBJECTS = \
|
||||||
|
$(am_src_processor_module_serialize_unittest_OBJECTS)
|
||||||
|
src_processor_module_serialize_unittest_DEPENDENCIES = \
|
||||||
|
src/processor/basic_code_modules.lo \
|
||||||
|
src/processor/basic_source_line_resolver.lo \
|
||||||
|
src/processor/call_stack.lo src/processor/logging.lo \
|
||||||
|
src/processor/pathname_stripper.lo
|
||||||
am_src_processor_pathname_stripper_unittest_OBJECTS = \
|
am_src_processor_pathname_stripper_unittest_OBJECTS = \
|
||||||
src/processor/pathname_stripper_unittest.$(OBJEXT)
|
src/processor/pathname_stripper_unittest.$(OBJEXT)
|
||||||
src_processor_pathname_stripper_unittest_OBJECTS = \
|
src_processor_pathname_stripper_unittest_OBJECTS = \
|
||||||
@@ -240,6 +253,7 @@ SOURCES = $(src_libbreakpad_la_SOURCES) \
|
|||||||
$(src_processor_minidump_dump_SOURCES) \
|
$(src_processor_minidump_dump_SOURCES) \
|
||||||
$(src_processor_minidump_processor_unittest_SOURCES) \
|
$(src_processor_minidump_processor_unittest_SOURCES) \
|
||||||
$(src_processor_minidump_stackwalk_SOURCES) \
|
$(src_processor_minidump_stackwalk_SOURCES) \
|
||||||
|
$(src_processor_module_serialize_unittest_SOURCES) \
|
||||||
$(src_processor_pathname_stripper_unittest_SOURCES) \
|
$(src_processor_pathname_stripper_unittest_SOURCES) \
|
||||||
$(src_processor_postfix_evaluator_unittest_SOURCES) \
|
$(src_processor_postfix_evaluator_unittest_SOURCES) \
|
||||||
$(src_processor_range_map_unittest_SOURCES) \
|
$(src_processor_range_map_unittest_SOURCES) \
|
||||||
@@ -251,6 +265,7 @@ DIST_SOURCES = $(src_libbreakpad_la_SOURCES) \
|
|||||||
$(src_processor_minidump_dump_SOURCES) \
|
$(src_processor_minidump_dump_SOURCES) \
|
||||||
$(src_processor_minidump_processor_unittest_SOURCES) \
|
$(src_processor_minidump_processor_unittest_SOURCES) \
|
||||||
$(src_processor_minidump_stackwalk_SOURCES) \
|
$(src_processor_minidump_stackwalk_SOURCES) \
|
||||||
|
$(src_processor_module_serialize_unittest_SOURCES) \
|
||||||
$(src_processor_pathname_stripper_unittest_SOURCES) \
|
$(src_processor_pathname_stripper_unittest_SOURCES) \
|
||||||
$(src_processor_postfix_evaluator_unittest_SOURCES) \
|
$(src_processor_postfix_evaluator_unittest_SOURCES) \
|
||||||
$(src_processor_range_map_unittest_SOURCES) \
|
$(src_processor_range_map_unittest_SOURCES) \
|
||||||
@@ -401,6 +416,7 @@ src_libbreakpad_la_SOURCES = \
|
|||||||
src/google_breakpad/processor/minidump_processor.h \
|
src/google_breakpad/processor/minidump_processor.h \
|
||||||
src/google_breakpad/processor/process_state.h \
|
src/google_breakpad/processor/process_state.h \
|
||||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||||
|
src/google_breakpad/processor/source_line_resolver_module_cache_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 \
|
||||||
src/google_breakpad/processor/stackwalker.h \
|
src/google_breakpad/processor/stackwalker.h \
|
||||||
@@ -415,6 +431,8 @@ src_libbreakpad_la_SOURCES = \
|
|||||||
src/processor/call_stack.cc \
|
src/processor/call_stack.cc \
|
||||||
src/processor/contained_range_map-inl.h \
|
src/processor/contained_range_map-inl.h \
|
||||||
src/processor/contained_range_map.h \
|
src/processor/contained_range_map.h \
|
||||||
|
src/processor/disk_module_cache.cc \
|
||||||
|
src/processor/disk_module_cache.h \
|
||||||
src/processor/linked_ptr.h \
|
src/processor/linked_ptr.h \
|
||||||
src/processor/logging.h \
|
src/processor/logging.h \
|
||||||
src/processor/logging.cc \
|
src/processor/logging.cc \
|
||||||
@@ -508,6 +526,16 @@ src_processor_range_map_unittest_LDADD = \
|
|||||||
src/processor/logging.lo \
|
src/processor/logging.lo \
|
||||||
src/processor/pathname_stripper.lo
|
src/processor/pathname_stripper.lo
|
||||||
|
|
||||||
|
src_processor_module_serialize_unittest_SOURCES = \
|
||||||
|
src/processor/module_serialize_unittest.cc
|
||||||
|
|
||||||
|
src_processor_module_serialize_unittest_LDADD = \
|
||||||
|
src/processor/basic_code_modules.lo \
|
||||||
|
src/processor/basic_source_line_resolver.lo \
|
||||||
|
src/processor/call_stack.lo \
|
||||||
|
src/processor/logging.lo \
|
||||||
|
src/processor/pathname_stripper.lo
|
||||||
|
|
||||||
src_processor_stackwalker_selftest_SOURCES = \
|
src_processor_stackwalker_selftest_SOURCES = \
|
||||||
src/processor/stackwalker_selftest.cc
|
src/processor/stackwalker_selftest.cc
|
||||||
|
|
||||||
@@ -541,6 +569,7 @@ src_processor_minidump_stackwalk_LDADD = \
|
|||||||
src/processor/basic_code_modules.lo \
|
src/processor/basic_code_modules.lo \
|
||||||
src/processor/basic_source_line_resolver.lo \
|
src/processor/basic_source_line_resolver.lo \
|
||||||
src/processor/call_stack.lo \
|
src/processor/call_stack.lo \
|
||||||
|
src/processor/disk_module_cache.lo \
|
||||||
src/processor/logging.lo \
|
src/processor/logging.lo \
|
||||||
src/processor/minidump.lo \
|
src/processor/minidump.lo \
|
||||||
src/processor/minidump_processor.lo \
|
src/processor/minidump_processor.lo \
|
||||||
@@ -778,6 +807,8 @@ src/processor/basic_source_line_resolver.lo: \
|
|||||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
src/processor/call_stack.lo: src/processor/$(am__dirstamp) \
|
src/processor/call_stack.lo: src/processor/$(am__dirstamp) \
|
||||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
src/processor/disk_module_cache.lo: src/processor/$(am__dirstamp) \
|
||||||
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
src/processor/logging.lo: src/processor/$(am__dirstamp) \
|
src/processor/logging.lo: src/processor/$(am__dirstamp) \
|
||||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
src/processor/minidump.lo: src/processor/$(am__dirstamp) \
|
src/processor/minidump.lo: src/processor/$(am__dirstamp) \
|
||||||
@@ -883,6 +914,12 @@ src/processor/minidump_stackwalk.$(OBJEXT): \
|
|||||||
src/processor/minidump_stackwalk$(EXEEXT): $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp)
|
src/processor/minidump_stackwalk$(EXEEXT): $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp)
|
||||||
@rm -f src/processor/minidump_stackwalk$(EXEEXT)
|
@rm -f src/processor/minidump_stackwalk$(EXEEXT)
|
||||||
$(CXXLINK) $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_LDADD) $(LIBS)
|
$(CXXLINK) $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_LDADD) $(LIBS)
|
||||||
|
src/processor/module_serialize_unittest.$(OBJEXT): \
|
||||||
|
src/processor/$(am__dirstamp) \
|
||||||
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
src/processor/module_serialize_unittest$(EXEEXT): $(src_processor_module_serialize_unittest_OBJECTS) $(src_processor_module_serialize_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
|
||||||
|
@rm -f src/processor/module_serialize_unittest$(EXEEXT)
|
||||||
|
$(CXXLINK) $(src_processor_module_serialize_unittest_OBJECTS) $(src_processor_module_serialize_unittest_LDADD) $(LIBS)
|
||||||
src/processor/pathname_stripper_unittest.$(OBJEXT): \
|
src/processor/pathname_stripper_unittest.$(OBJEXT): \
|
||||||
src/processor/$(am__dirstamp) \
|
src/processor/$(am__dirstamp) \
|
||||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||||
@@ -919,6 +956,8 @@ mostlyclean-compile:
|
|||||||
-rm -f src/processor/call_stack.$(OBJEXT)
|
-rm -f src/processor/call_stack.$(OBJEXT)
|
||||||
-rm -f src/processor/call_stack.lo
|
-rm -f src/processor/call_stack.lo
|
||||||
-rm -f src/processor/contained_range_map_unittest.$(OBJEXT)
|
-rm -f src/processor/contained_range_map_unittest.$(OBJEXT)
|
||||||
|
-rm -f src/processor/disk_module_cache.$(OBJEXT)
|
||||||
|
-rm -f src/processor/disk_module_cache.lo
|
||||||
-rm -f src/processor/logging.$(OBJEXT)
|
-rm -f src/processor/logging.$(OBJEXT)
|
||||||
-rm -f src/processor/logging.lo
|
-rm -f src/processor/logging.lo
|
||||||
-rm -f src/processor/minidump.$(OBJEXT)
|
-rm -f src/processor/minidump.$(OBJEXT)
|
||||||
@@ -928,6 +967,7 @@ mostlyclean-compile:
|
|||||||
-rm -f src/processor/minidump_processor.lo
|
-rm -f src/processor/minidump_processor.lo
|
||||||
-rm -f src/processor/minidump_processor_unittest.$(OBJEXT)
|
-rm -f src/processor/minidump_processor_unittest.$(OBJEXT)
|
||||||
-rm -f src/processor/minidump_stackwalk.$(OBJEXT)
|
-rm -f src/processor/minidump_stackwalk.$(OBJEXT)
|
||||||
|
-rm -f src/processor/module_serialize_unittest.$(OBJEXT)
|
||||||
-rm -f src/processor/pathname_stripper.$(OBJEXT)
|
-rm -f src/processor/pathname_stripper.$(OBJEXT)
|
||||||
-rm -f src/processor/pathname_stripper.lo
|
-rm -f src/processor/pathname_stripper.lo
|
||||||
-rm -f src/processor/pathname_stripper_unittest.$(OBJEXT)
|
-rm -f src/processor/pathname_stripper_unittest.$(OBJEXT)
|
||||||
@@ -958,12 +998,14 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver_unittest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/call_stack.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/call_stack.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/contained_range_map_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/contained_range_map_unittest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/disk_module_cache.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor_unittest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_stackwalk.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_stackwalk.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/module_serialize_unittest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper_unittest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/postfix_evaluator_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/postfix_evaluator_unittest.Po@am__quote@
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
#endif // BSLR_NO_HASH_MAP
|
#endif // BSLR_NO_HASH_MAP
|
||||||
|
|
||||||
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
||||||
|
#include "google_breakpad/processor/source_line_resolver_module_cache_interface.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
@@ -56,9 +57,11 @@ using std::map;
|
|||||||
using __gnu_cxx::hash_map;
|
using __gnu_cxx::hash_map;
|
||||||
#endif // BSLR_NO_HASH_MAP
|
#endif // BSLR_NO_HASH_MAP
|
||||||
|
|
||||||
|
|
||||||
class BasicSourceLineResolver : public SourceLineResolverInterface {
|
class BasicSourceLineResolver : public SourceLineResolverInterface {
|
||||||
public:
|
public:
|
||||||
BasicSourceLineResolver();
|
BasicSourceLineResolver();
|
||||||
|
BasicSourceLineResolver(SourceLineResolverModuleCacheInterface *);
|
||||||
virtual ~BasicSourceLineResolver();
|
virtual ~BasicSourceLineResolver();
|
||||||
|
|
||||||
// SourceLineResolverInterface methods, see source_line_resolver_interface.h
|
// SourceLineResolverInterface methods, see source_line_resolver_interface.h
|
||||||
@@ -73,6 +76,8 @@ class BasicSourceLineResolver : public SourceLineResolverInterface {
|
|||||||
|
|
||||||
virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const;
|
virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const;
|
||||||
|
|
||||||
|
static bool ModuleRoundTripTest(const string &map_file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class T> class MemAddrMap;
|
template<class T> class MemAddrMap;
|
||||||
struct Line;
|
struct Line;
|
||||||
@@ -97,10 +102,16 @@ class BasicSourceLineResolver : public SourceLineResolverInterface {
|
|||||||
typedef hash_map<string, Module*, HashString> ModuleMap;
|
typedef hash_map<string, Module*, HashString> ModuleMap;
|
||||||
#endif // BSLR_NO_HASH_MAP
|
#endif // BSLR_NO_HASH_MAP
|
||||||
ModuleMap *modules_;
|
ModuleMap *modules_;
|
||||||
|
SourceLineResolverModuleCacheInterface *module_cache_;
|
||||||
|
|
||||||
// Disallow unwanted copy ctor and assignment operator
|
// Disallow unwanted copy ctor and assignment operator
|
||||||
BasicSourceLineResolver(const BasicSourceLineResolver&);
|
BasicSourceLineResolver(const BasicSourceLineResolver&);
|
||||||
void operator=(const BasicSourceLineResolver&);
|
void operator=(const BasicSourceLineResolver&);
|
||||||
|
|
||||||
|
friend bool Equals(const BasicSourceLineResolver::Function &a,
|
||||||
|
const BasicSourceLineResolver::Function &b);
|
||||||
|
|
||||||
|
friend class ModuleSerializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) 2007, 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.
|
||||||
|
|
||||||
|
// Abstract interface to store and retrieve cached data for module
|
||||||
|
// symbols.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_MODULE_CACHE_INTERFACE_H__
|
||||||
|
#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_MODULE_CACHE_INTERFACE_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::istream;
|
||||||
|
using std::ostream;
|
||||||
|
|
||||||
|
class SourceLineResolverModuleCacheInterface {
|
||||||
|
public:
|
||||||
|
virtual ~SourceLineResolverModuleCacheInterface() {}
|
||||||
|
|
||||||
|
// Retrieve the symbol data associated with a module
|
||||||
|
virtual bool GetModuleData(const string &symbol_file,
|
||||||
|
istream **data_stream) = 0;
|
||||||
|
|
||||||
|
// Get a stream to which the data associated with a module
|
||||||
|
// can be stored
|
||||||
|
virtual bool BeginSetModuleData(const string &symbol_file,
|
||||||
|
ostream **data_stream) = 0;
|
||||||
|
// Finish setting the data associated with this module,
|
||||||
|
// data should already have been written to the stream
|
||||||
|
virtual bool EndSetModuleData(const string &symbol_file,
|
||||||
|
ostream **data_stream) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// SourceLineResolverModuleCacheInterface cannot be instantiated
|
||||||
|
// except by subclasses
|
||||||
|
SourceLineResolverModuleCacheInterface() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_MODULE_CACHE_INTERFACE_H__
|
@@ -39,6 +39,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "processor/address_map.h"
|
#include "processor/address_map.h"
|
||||||
|
#include "processor/equals.h"
|
||||||
#include "processor/logging.h"
|
#include "processor/logging.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
@@ -87,6 +88,12 @@ void AddressMap<AddressType, EntryType>::Clear() {
|
|||||||
map_.clear();
|
map_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
bool AddressMap<AddressType, EntryType>::Equals(
|
||||||
|
const AddressMap<AddressType, EntryType> &other) const {
|
||||||
|
return google_breakpad::Equals(map_, other.map_);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
||||||
#endif // PROCESSOR_ADDRESS_MAP_INL_H__
|
#endif // PROCESSOR_ADDRESS_MAP_INL_H__
|
||||||
|
@@ -64,6 +64,8 @@ class AddressMap {
|
|||||||
// initially created.
|
// initially created.
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
bool Equals(const AddressMap<AddressType, EntryType> &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Convenience types.
|
// Convenience types.
|
||||||
typedef std::map<AddressType, EntryType> AddressToEntryMap;
|
typedef std::map<AddressType, EntryType> AddressToEntryMap;
|
||||||
@@ -72,6 +74,8 @@ class AddressMap {
|
|||||||
|
|
||||||
// Maps the address of each entry to an EntryType.
|
// Maps the address of each entry to an EntryType.
|
||||||
AddressToEntryMap map_;
|
AddressToEntryMap map_;
|
||||||
|
|
||||||
|
friend class ModuleSerializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
@@ -33,7 +33,9 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "processor/equals.h"
|
||||||
#include "processor/address_map-inl.h"
|
#include "processor/address_map-inl.h"
|
||||||
#include "processor/contained_range_map-inl.h"
|
#include "processor/contained_range_map-inl.h"
|
||||||
#include "processor/range_map-inl.h"
|
#include "processor/range_map-inl.h"
|
||||||
@@ -61,10 +63,17 @@ struct BasicSourceLineResolver::Line {
|
|||||||
, source_file_id(file_id)
|
, source_file_id(file_id)
|
||||||
, line(source_line) { }
|
, line(source_line) { }
|
||||||
|
|
||||||
|
bool operator==(const Line &other) const {
|
||||||
|
return address == other.address &&
|
||||||
|
size == other.size &&
|
||||||
|
source_file_id == other.source_file_id &&
|
||||||
|
line == other.line;
|
||||||
|
}
|
||||||
|
|
||||||
MemAddr address;
|
MemAddr address;
|
||||||
MemAddr size;
|
MemAddr size;
|
||||||
int source_file_id;
|
u_int32_t source_file_id;
|
||||||
int line;
|
u_int32_t line;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BasicSourceLineResolver::Function {
|
struct BasicSourceLineResolver::Function {
|
||||||
@@ -80,11 +89,21 @@ struct BasicSourceLineResolver::Function {
|
|||||||
MemAddr size;
|
MemAddr size;
|
||||||
|
|
||||||
// The size of parameters passed to this function on the stack.
|
// The size of parameters passed to this function on the stack.
|
||||||
int parameter_size;
|
u_int32_t parameter_size;
|
||||||
|
|
||||||
RangeMap< MemAddr, linked_ptr<Line> > lines;
|
RangeMap< MemAddr, linked_ptr<Line> > lines;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// doesn't really belong here, but I can't put it anywhere else...
|
||||||
|
inline bool Equals(const BasicSourceLineResolver::Function &a,
|
||||||
|
const BasicSourceLineResolver::Function &b)
|
||||||
|
{
|
||||||
|
return a.name == b.name &&
|
||||||
|
a.address == b.address &&
|
||||||
|
a.size == b.size &&
|
||||||
|
Equals(a.lines, b.lines);
|
||||||
|
}
|
||||||
|
|
||||||
struct BasicSourceLineResolver::PublicSymbol {
|
struct BasicSourceLineResolver::PublicSymbol {
|
||||||
PublicSymbol(const string& set_name,
|
PublicSymbol(const string& set_name,
|
||||||
MemAddr set_address,
|
MemAddr set_address,
|
||||||
@@ -93,13 +112,19 @@ struct BasicSourceLineResolver::PublicSymbol {
|
|||||||
address(set_address),
|
address(set_address),
|
||||||
parameter_size(set_parameter_size) {}
|
parameter_size(set_parameter_size) {}
|
||||||
|
|
||||||
|
bool operator==(const PublicSymbol &other) const {
|
||||||
|
return name == other.name &&
|
||||||
|
address == other.address &&
|
||||||
|
parameter_size == other.parameter_size;
|
||||||
|
}
|
||||||
|
|
||||||
string name;
|
string name;
|
||||||
MemAddr address;
|
MemAddr address;
|
||||||
|
|
||||||
// If the public symbol is used as a function entry point, parameter_size
|
// 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
|
// is set to the size of the parameters passed to the function on the
|
||||||
// stack, if known.
|
// stack, if known.
|
||||||
int parameter_size;
|
u_int32_t parameter_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BasicSourceLineResolver::Module {
|
class BasicSourceLineResolver::Module {
|
||||||
@@ -116,12 +141,15 @@ class BasicSourceLineResolver::Module {
|
|||||||
// any returned StackFrameInfo object.
|
// any returned StackFrameInfo object.
|
||||||
StackFrameInfo* LookupAddress(StackFrame *frame) const;
|
StackFrameInfo* LookupAddress(StackFrame *frame) const;
|
||||||
|
|
||||||
|
bool Equals(const Module &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BasicSourceLineResolver;
|
friend class BasicSourceLineResolver;
|
||||||
|
|
||||||
#ifdef BSLR_NO_HASH_MAP
|
#ifdef BSLR_NO_HASH_MAP
|
||||||
typedef map<int, string> FileMap;
|
typedef map<u_int32_t, string> FileMap;
|
||||||
#else // BSLR_NO_HASH_MAP
|
#else // BSLR_NO_HASH_MAP
|
||||||
typedef hash_map<int, string> FileMap;
|
typedef hash_map<u_int32_t, string> FileMap;
|
||||||
#endif // BSLR_NO_HASH_MAP
|
#endif // BSLR_NO_HASH_MAP
|
||||||
|
|
||||||
// The types for stack_info_. This is equivalent to MS DIA's
|
// The types for stack_info_. This is equivalent to MS DIA's
|
||||||
@@ -177,9 +205,391 @@ class BasicSourceLineResolver::Module {
|
|||||||
// as certain types.
|
// as certain types.
|
||||||
ContainedRangeMap< MemAddr, linked_ptr<StackFrameInfo> >
|
ContainedRangeMap< MemAddr, linked_ptr<StackFrameInfo> >
|
||||||
stack_info_[STACK_INFO_LAST];
|
stack_info_[STACK_INFO_LAST];
|
||||||
|
|
||||||
|
friend class ModuleSerializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
BasicSourceLineResolver::BasicSourceLineResolver() : modules_(new ModuleMap) {
|
|
||||||
|
class ModuleSerializer {
|
||||||
|
public:
|
||||||
|
ModuleSerializer(std::istream *stream) : instream_(stream),
|
||||||
|
outstream_(NULL) {}
|
||||||
|
ModuleSerializer(std::ostream *stream) : instream_(NULL),
|
||||||
|
outstream_(stream) {}
|
||||||
|
|
||||||
|
bool Serialize(const BasicSourceLineResolver::Module &module) {
|
||||||
|
if (!outstream_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outstream_->seekp(0, std::ios_base::beg);
|
||||||
|
Write(SERIALIZE_FORMAT);
|
||||||
|
Write(module.files_);
|
||||||
|
Write(module.functions_);
|
||||||
|
Write(module.public_symbols_);
|
||||||
|
for (int i = BasicSourceLineResolver::Module::STACK_INFO_FPO;
|
||||||
|
i < BasicSourceLineResolver::Module::STACK_INFO_LAST; i++)
|
||||||
|
Write(module.stack_info_[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Deserialize(BasicSourceLineResolver::Module &module) {
|
||||||
|
if (!instream_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
instream_->seekg(0, std::ios_base::beg);
|
||||||
|
u_int32_t format;
|
||||||
|
Read(format);
|
||||||
|
if (format != SERIALIZE_FORMAT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Read(module.files_);
|
||||||
|
Read(module.functions_);
|
||||||
|
Read(module.public_symbols_);
|
||||||
|
for (int i = BasicSourceLineResolver::Module::STACK_INFO_FPO;
|
||||||
|
i < BasicSourceLineResolver::Module::STACK_INFO_LAST; i++)
|
||||||
|
Read(module.stack_info_[i]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Increment this if changing the serializing format
|
||||||
|
static const u_int32_t SERIALIZE_FORMAT = 1;
|
||||||
|
|
||||||
|
void Write(const u_int32_t data) {
|
||||||
|
outstream_->write(reinterpret_cast<const char*>(&data), sizeof(u_int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const u_int64_t data) {
|
||||||
|
outstream_->write(reinterpret_cast<const char*>(&data), sizeof(u_int64_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Read(u_int32_t &data) {
|
||||||
|
instream_->read(reinterpret_cast<char*>(&data), sizeof(u_int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Read(u_int64_t &data) {
|
||||||
|
instream_->read(reinterpret_cast<char*>(&data), sizeof(u_int64_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize strings as a length + character array (not null terminated)
|
||||||
|
// pad out to sizeof(int)
|
||||||
|
void Write(const string &data) {
|
||||||
|
if (data.empty()) {
|
||||||
|
Write((u_int32_t)0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int32_t extra = sizeof(u_int32_t) - (data.size() % sizeof(u_int32_t));
|
||||||
|
Write((u_int32_t)data.size() + extra);
|
||||||
|
outstream_->write(data.c_str(), data.size());
|
||||||
|
char c = '\0';
|
||||||
|
for (int i=0; i<extra; i++)
|
||||||
|
outstream_->write(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Read(string &data) {
|
||||||
|
u_int32_t length;
|
||||||
|
Read(length);
|
||||||
|
|
||||||
|
if (length > 0) {
|
||||||
|
vector<char> string_bytes(length);
|
||||||
|
instream_->read(&string_bytes[0], length);
|
||||||
|
data = &string_bytes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename k, typename d>
|
||||||
|
void Write(const map<k, d> &data) {
|
||||||
|
Write((u_int32_t)data.size());
|
||||||
|
for (typename map<k,d>::const_iterator it = data.begin();
|
||||||
|
it != data.end(); it++) {
|
||||||
|
Write(it->first);
|
||||||
|
Write(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename k, typename v>
|
||||||
|
void Read(map<k, v> &data) {
|
||||||
|
u_int32_t length;
|
||||||
|
Read(length);
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
k key;
|
||||||
|
v value;
|
||||||
|
Read(key);
|
||||||
|
Read(value);
|
||||||
|
data.insert(make_pair(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BSLR_NO_HASH_MAP
|
||||||
|
template<typename k, typename d>
|
||||||
|
void Write(const hash_map<k, d> &data) {
|
||||||
|
Write((u_int32_t)data.size());
|
||||||
|
for (typename hash_map<k,d>::const_iterator it = data.begin();
|
||||||
|
it != data.end(); it++) {
|
||||||
|
Write(it->first);
|
||||||
|
Write(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename k, typename v>
|
||||||
|
void Read(hash_map<k, v> &data) {
|
||||||
|
u_int32_t length;
|
||||||
|
Read(length);
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
data.resize(length);
|
||||||
|
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
k key;
|
||||||
|
v value;
|
||||||
|
Read(key);
|
||||||
|
Read(value);
|
||||||
|
data.insert(make_pair(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Write(const RangeMap<AddressType, EntryType> &data) {
|
||||||
|
Write((u_int32_t)data.map_.size());
|
||||||
|
for (typename RangeMap<AddressType, EntryType>::MapConstIterator it =
|
||||||
|
data.map_.begin(); it != data.map_.end(); it++) {
|
||||||
|
Write(it->first);
|
||||||
|
Write<AddressType, EntryType>(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Read(RangeMap<AddressType, EntryType> &data) {
|
||||||
|
// Can't instantiate Range(), so manually read in the
|
||||||
|
// AddressMap here.
|
||||||
|
u_int32_t length;
|
||||||
|
Read(length);
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
AddressType address, range_address;
|
||||||
|
EntryType entry;
|
||||||
|
// map key
|
||||||
|
Read(address);
|
||||||
|
// Range values
|
||||||
|
Read(range_address);
|
||||||
|
Read(entry);
|
||||||
|
data.map_.insert(make_pair(address,
|
||||||
|
typename RangeMap<AddressType, EntryType>::Range(range_address, entry)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Write(const typename RangeMap<AddressType, EntryType>::Range &data) {
|
||||||
|
Write(data.base_);
|
||||||
|
Write(data.entry_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Write(const AddressMap<AddressType, EntryType> &data) {
|
||||||
|
Write(data.map_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Read(AddressMap<AddressType, EntryType> &data) {
|
||||||
|
Read(data.map_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Write(const ContainedRangeMap<AddressType, EntryType> &data) {
|
||||||
|
Write(data.base_);
|
||||||
|
Write(data.entry_);
|
||||||
|
if (data.map_) {
|
||||||
|
// write this as a marker
|
||||||
|
Write((u_int32_t)1);
|
||||||
|
Write(*data.map_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write((u_int32_t)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Read(ContainedRangeMap<AddressType, EntryType> &data) {
|
||||||
|
// sort of evil, but that's ok
|
||||||
|
AddressType *base_ptr = const_cast<AddressType*>(&data.base_);
|
||||||
|
Read(*base_ptr);
|
||||||
|
EntryType *entry_ptr = const_cast<EntryType*>(&data.entry_);
|
||||||
|
Read(*entry_ptr);
|
||||||
|
|
||||||
|
u_int32_t marker;
|
||||||
|
Read(marker);
|
||||||
|
if (marker == 1) {
|
||||||
|
data.map_ = new typename ContainedRangeMap<AddressType, EntryType>::AddressToRangeMap();
|
||||||
|
Read(*data.map_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Write(const ContainedRangeMap<AddressType, EntryType> * const &data) {
|
||||||
|
if (data) {
|
||||||
|
// write this as a marker
|
||||||
|
Write((u_int32_t)1);
|
||||||
|
Write<AddressType, EntryType>(*data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write((u_int32_t)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
void Read(ContainedRangeMap<AddressType, EntryType> *&data) {
|
||||||
|
u_int32_t marker;
|
||||||
|
Read(marker);
|
||||||
|
if (marker == 1) {
|
||||||
|
data = new ContainedRangeMap<AddressType, EntryType>();
|
||||||
|
Read<AddressType, EntryType>(*data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const BasicSourceLineResolver::Function &data) {
|
||||||
|
Write(data.name);
|
||||||
|
Write(data.address);
|
||||||
|
Write(data.size);
|
||||||
|
Write(data.parameter_size);
|
||||||
|
Write(data.lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read this as a pointer because there's no zero-argument
|
||||||
|
// constructor.
|
||||||
|
void Read(BasicSourceLineResolver::Function *&data) {
|
||||||
|
string name;
|
||||||
|
SourceLineResolverInterface::MemAddr address;
|
||||||
|
SourceLineResolverInterface::MemAddr size;
|
||||||
|
u_int32_t parameter_size;
|
||||||
|
|
||||||
|
Read(name);
|
||||||
|
Read(address);
|
||||||
|
Read(size);
|
||||||
|
Read(parameter_size);
|
||||||
|
data = new BasicSourceLineResolver::Function(name, address, size,
|
||||||
|
parameter_size);
|
||||||
|
Read(data->lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const BasicSourceLineResolver::PublicSymbol &data) {
|
||||||
|
Write(data.name);
|
||||||
|
Write(data.address);
|
||||||
|
Write(data.parameter_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read this as a pointer because there's no zero-argument
|
||||||
|
// constructor.
|
||||||
|
void Read(BasicSourceLineResolver::PublicSymbol *&data) {
|
||||||
|
string name;
|
||||||
|
SourceLineResolverInterface::MemAddr address;
|
||||||
|
u_int32_t parameter_size;
|
||||||
|
Read(name);
|
||||||
|
Read(address);
|
||||||
|
Read(parameter_size);
|
||||||
|
data = new BasicSourceLineResolver::PublicSymbol(name, address,
|
||||||
|
parameter_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const BasicSourceLineResolver::Line &data) {
|
||||||
|
Write(data.address);
|
||||||
|
Write(data.size);
|
||||||
|
Write(data.source_file_id);
|
||||||
|
Write(data.line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read this as a pointer because there's no zero-argument
|
||||||
|
// constructor.
|
||||||
|
void Read(BasicSourceLineResolver::Line *&data) {
|
||||||
|
SourceLineResolverInterface::MemAddr address;
|
||||||
|
SourceLineResolverInterface::MemAddr size;
|
||||||
|
u_int32_t source_file_id;
|
||||||
|
u_int32_t line;
|
||||||
|
|
||||||
|
Read(address);
|
||||||
|
Read(size);
|
||||||
|
Read(source_file_id);
|
||||||
|
Read(line);
|
||||||
|
|
||||||
|
data = new BasicSourceLineResolver::Line(address, size, source_file_id,
|
||||||
|
line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const StackFrameInfo &data) {
|
||||||
|
Write(data.valid);
|
||||||
|
Write(data.prolog_size);
|
||||||
|
Write(data.epilog_size);
|
||||||
|
Write(data.parameter_size);
|
||||||
|
Write(data.saved_register_size);
|
||||||
|
Write(data.local_size);
|
||||||
|
Write(data.max_stack_size);
|
||||||
|
Write((u_int32_t)data.allocates_base_pointer);
|
||||||
|
Write(data.program_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just for consistency with the above methods.
|
||||||
|
void Read(StackFrameInfo *&data) {
|
||||||
|
data = new StackFrameInfo();
|
||||||
|
Read(data->valid);
|
||||||
|
Read(data->prolog_size);
|
||||||
|
Read(data->epilog_size);
|
||||||
|
Read(data->parameter_size);
|
||||||
|
Read(data->saved_register_size);
|
||||||
|
Read(data->local_size);
|
||||||
|
Read(data->max_stack_size);
|
||||||
|
u_int32_t allocates_base_pointer;
|
||||||
|
Read(allocates_base_pointer);
|
||||||
|
data->allocates_base_pointer = (allocates_base_pointer != 0);
|
||||||
|
Read(data->program_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Write(const linked_ptr<T> &data) {
|
||||||
|
if (data.get()) {
|
||||||
|
// write this as a marker
|
||||||
|
Write((u_int32_t)1);
|
||||||
|
Write(*data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write((u_int32_t)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Read(linked_ptr<T> &data) {
|
||||||
|
u_int32_t marker;
|
||||||
|
Read(marker);
|
||||||
|
if (marker == 1) {
|
||||||
|
T *thing;
|
||||||
|
// Read will allocate the pointer
|
||||||
|
Read(thing);
|
||||||
|
data.reset(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream *instream_;
|
||||||
|
std::ostream *outstream_;
|
||||||
|
};
|
||||||
|
|
||||||
|
BasicSourceLineResolver::BasicSourceLineResolver() :
|
||||||
|
modules_(new ModuleMap),
|
||||||
|
module_cache_(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicSourceLineResolver::BasicSourceLineResolver(SourceLineResolverModuleCacheInterface *module_cache) :
|
||||||
|
modules_(new ModuleMap),
|
||||||
|
module_cache_(module_cache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicSourceLineResolver::~BasicSourceLineResolver() {
|
BasicSourceLineResolver::~BasicSourceLineResolver() {
|
||||||
@@ -202,11 +612,34 @@ bool BasicSourceLineResolver::LoadModule(const string &module_name,
|
|||||||
map_file;
|
map_file;
|
||||||
|
|
||||||
Module *module = new Module(module_name);
|
Module *module = new Module(module_name);
|
||||||
|
|
||||||
|
// First see if we have a cache, and if so,
|
||||||
|
// if the cache contains this module
|
||||||
|
istream *instream;
|
||||||
|
if (module_cache_ &&
|
||||||
|
module_cache_->GetModuleData(map_file, &instream)) {
|
||||||
|
ModuleSerializer serializer(instream);
|
||||||
|
serializer.Deserialize(*module);
|
||||||
|
delete instream;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Otherwise load from file
|
||||||
if (!module->LoadMap(map_file)) {
|
if (!module->LoadMap(map_file)) {
|
||||||
delete module;
|
delete module;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have a cache, then store the result
|
||||||
|
ostream *outstream;
|
||||||
|
if (module_cache_ &&
|
||||||
|
module_cache_->BeginSetModuleData(map_file, &outstream)) {
|
||||||
|
ModuleSerializer serializer(outstream);
|
||||||
|
serializer.Serialize(*module);
|
||||||
|
module_cache_->EndSetModuleData(map_file, &outstream);
|
||||||
|
delete outstream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
modules_->insert(make_pair(module_name, module));
|
modules_->insert(make_pair(module_name, module));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -402,6 +835,23 @@ StackFrameInfo* BasicSourceLineResolver::Module::LookupAddress(
|
|||||||
return frame_info.release();
|
return frame_info.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BasicSourceLineResolver::Module::Equals(const Module &other) const {
|
||||||
|
return
|
||||||
|
google_breakpad::Equals(files_, other.files_) &&
|
||||||
|
google_breakpad::Equals(functions_, other.functions_) &&
|
||||||
|
google_breakpad::Equals(public_symbols_, other.public_symbols_) &&
|
||||||
|
google_breakpad::Equals(stack_info_[STACK_INFO_FPO],
|
||||||
|
other.stack_info_[STACK_INFO_FPO]) &&
|
||||||
|
google_breakpad::Equals(stack_info_[STACK_INFO_TRAP],
|
||||||
|
other.stack_info_[STACK_INFO_TRAP]) &&
|
||||||
|
google_breakpad::Equals(stack_info_[STACK_INFO_TSS],
|
||||||
|
other.stack_info_[STACK_INFO_TSS]) &&
|
||||||
|
google_breakpad::Equals(stack_info_[STACK_INFO_STANDARD],
|
||||||
|
other.stack_info_[STACK_INFO_STANDARD]) &&
|
||||||
|
google_breakpad::Equals(stack_info_[STACK_INFO_FRAME_DATA],
|
||||||
|
other.stack_info_[STACK_INFO_FRAME_DATA]);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool BasicSourceLineResolver::Module::Tokenize(char *line, int max_tokens,
|
bool BasicSourceLineResolver::Module::Tokenize(char *line, int max_tokens,
|
||||||
vector<char*> *tokens) {
|
vector<char*> *tokens) {
|
||||||
@@ -611,4 +1061,44 @@ size_t BasicSourceLineResolver::HashString::operator()(const string &s) const {
|
|||||||
}
|
}
|
||||||
#endif // BSLR_NO_HASH_MAP
|
#endif // BSLR_NO_HASH_MAP
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool BasicSourceLineResolver::ModuleRoundTripTest(const string &map_file) {
|
||||||
|
Module *module = new Module("test");
|
||||||
|
if (!module->LoadMap(map_file)) {
|
||||||
|
BPLOG(ERROR) << "Failed to load map file!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!module->Equals(*module)) { // sanity check
|
||||||
|
BPLOG(ERROR) << "Failed sanity check!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream memory_stream(std::ios::in | std::ios::out |
|
||||||
|
std::ios::binary);
|
||||||
|
memory_stream.exceptions(std::ios::eofbit | std::ios::failbit |
|
||||||
|
std::ios::badbit);
|
||||||
|
ModuleSerializer serializer(static_cast<ostream*>(&memory_stream));
|
||||||
|
if (!serializer.Serialize(*module)) {
|
||||||
|
BPLOG(ERROR) << "Failed to serialize Module!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Serialized " << memory_stream.tellp() << " bytes.";
|
||||||
|
|
||||||
|
Module *new_module = new Module("test");
|
||||||
|
ModuleSerializer deserializer(static_cast<istream*>(&memory_stream));
|
||||||
|
if (!deserializer.Deserialize(*new_module)) {
|
||||||
|
BPLOG(ERROR) << "Failed to deserialize Module!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!module->Equals(*new_module)) {
|
||||||
|
BPLOG(ERROR) << "Deserialized module not equivalent to original!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BPLOG(INFO) << "Round trip successful!";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "processor/contained_range_map.h"
|
#include "processor/contained_range_map.h"
|
||||||
|
#include "processor/equals.h"
|
||||||
#include "processor/logging.h"
|
#include "processor/logging.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -185,6 +186,23 @@ void ContainedRangeMap<AddressType, EntryType>::Clear() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
bool ContainedRangeMap<AddressType, EntryType>::Equals(
|
||||||
|
const ContainedRangeMap<AddressType, EntryType> &other) const
|
||||||
|
{
|
||||||
|
bool equal;
|
||||||
|
if (map_ && other.map_) {
|
||||||
|
equal = google_breakpad::Equals(*map_, *other.map_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// otherwise if they're both NULL they're equal
|
||||||
|
equal = map_ == other.map_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return equal &&
|
||||||
|
google_breakpad::Equals(base_, other.base_) &&
|
||||||
|
google_breakpad::Equals(entry_, other.entry_);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
@@ -102,6 +102,8 @@ class ContainedRangeMap {
|
|||||||
// empty state when called on the root node.
|
// empty state when called on the root node.
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
bool Equals(const ContainedRangeMap<AddressType, EntryType> &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// AddressToRangeMap stores pointers. This makes reparenting simpler in
|
// AddressToRangeMap stores pointers. This makes reparenting simpler in
|
||||||
// StoreRange, because it doesn't need to copy entire objects.
|
// StoreRange, because it doesn't need to copy entire objects.
|
||||||
@@ -136,6 +138,8 @@ class ContainedRangeMap {
|
|||||||
// address. This is a pointer to avoid allocating map structures for
|
// address. This is a pointer to avoid allocating map structures for
|
||||||
// leaf nodes, where they are not needed.
|
// leaf nodes, where they are not needed.
|
||||||
AddressToRangeMap *map_;
|
AddressToRangeMap *map_;
|
||||||
|
|
||||||
|
friend class ModuleSerializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
218
src/processor/disk_module_cache.cc
Normal file
218
src/processor/disk_module_cache.cc
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
// Copyright (c) 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ios>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "processor/disk_module_cache.h"
|
||||||
|
#include "processor/logging.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::ostream;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::istream;
|
||||||
|
using std::ifstream;
|
||||||
|
using std::ios;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
// tempofstream writes data to a temporary file in the same
|
||||||
|
// directory as the file passed to the constructor.
|
||||||
|
// when closed, it renames the temporary file to the given filename.
|
||||||
|
class tempofstream : public ofstream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tempofstream(const char * filename, ios_base::openmode mode = ios_base::out);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
string tempname_;
|
||||||
|
string filename_;
|
||||||
|
};
|
||||||
|
|
||||||
|
tempofstream::tempofstream(const char * filename,
|
||||||
|
ios_base::openmode mode) : tempname_(""),
|
||||||
|
filename_(filename)
|
||||||
|
{
|
||||||
|
string name_template_s = filename_ + "XXXXXX";
|
||||||
|
vector<char> name_template(name_template_s.length() + 1);
|
||||||
|
std::copy(name_template_s.begin(), name_template_s.end(),
|
||||||
|
name_template.begin());
|
||||||
|
name_template[name_template.size() - 1] = '\0';
|
||||||
|
tempname_ = mktemp(&name_template[0]);
|
||||||
|
open(tempname_.c_str(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tempofstream::close()
|
||||||
|
{
|
||||||
|
ofstream::close();
|
||||||
|
rename(tempname_.c_str(), filename_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
DiskModuleCache::DiskModuleCache(string cache_directory) :
|
||||||
|
cache_directory_(cache_directory)
|
||||||
|
{
|
||||||
|
// ensure trailing slash in cache directory
|
||||||
|
if (cache_directory_[cache_directory_.length()] != '/')
|
||||||
|
cache_directory.append("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskModuleCache::GetModuleData(const string &symbol_file,
|
||||||
|
istream **data_stream)
|
||||||
|
{
|
||||||
|
if (!data_stream)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string cache_file = MapToCacheEntry(symbol_file);
|
||||||
|
if (cache_file.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*data_stream = new ifstream(cache_file.c_str(),
|
||||||
|
ios::in | ios::binary);
|
||||||
|
if (!**data_stream) {
|
||||||
|
delete *data_stream;
|
||||||
|
*data_stream = NULL;
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Symbol file " << symbol_file << " not cached";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BPLOG(INFO) << "Loading cached copy of symbol file " << symbol_file
|
||||||
|
<< " from " << cache_file;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskModuleCache::BeginSetModuleData(const string &symbol_file,
|
||||||
|
ostream **data_stream)
|
||||||
|
{
|
||||||
|
if (!data_stream)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string cache_file = MapToCacheEntry(symbol_file);
|
||||||
|
BPLOG(INFO) << "Writing cache entry " << cache_file;
|
||||||
|
if (!EnsurePathExists(cache_file.substr(0, cache_file.rfind('/'))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*data_stream = new tempofstream(cache_file.c_str(),
|
||||||
|
ios::out | ios::binary | ios::trunc);
|
||||||
|
if (!**data_stream) {
|
||||||
|
delete *data_stream;
|
||||||
|
*data_stream = NULL;
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Failed writing cache entry " << cache_file;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskModuleCache::EndSetModuleData(const string &symbol_file,
|
||||||
|
ostream **data_stream)
|
||||||
|
{
|
||||||
|
tempofstream *file_stream = dynamic_cast<tempofstream*>(*data_stream);
|
||||||
|
if (!file_stream) {
|
||||||
|
BPLOG(INFO) << "Error writing cache entry for " << symbol_file;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPLOG(INFO) << "Finished writing cache entry for " << symbol_file;
|
||||||
|
file_stream->close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We assume that symbol_file is in the Microsoft Symbol Server
|
||||||
|
// format, /path/debug_file/IDENTIFIER/debug_file.sym. We map
|
||||||
|
// this to /cache/path/debug_file/IDENTIFIER/debug_file.symcache.
|
||||||
|
// NOTE: this assumes unix style paths!
|
||||||
|
string DiskModuleCache::MapToCacheEntry(const string &symbol_file)
|
||||||
|
{
|
||||||
|
string::size_type pos = string::npos;
|
||||||
|
|
||||||
|
// we want the last three components in the path
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
pos = symbol_file.rfind('/', pos);
|
||||||
|
if (pos == string::npos)
|
||||||
|
return "";
|
||||||
|
// back up one character so we don't find this slash again
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
|
||||||
|
string cache_file(cache_directory_ +
|
||||||
|
symbol_file.substr(pos + 2));
|
||||||
|
pos = cache_file.length() - 4;
|
||||||
|
if (cache_file.compare(pos, 4, ".sym") == 0)
|
||||||
|
cache_file.replace(pos, 4, ".symcache");
|
||||||
|
|
||||||
|
return cache_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskModuleCache::EnsurePathExists(const string &path)
|
||||||
|
{
|
||||||
|
if (IsDir(path))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (mkdir(path.c_str(), 0755) == -1) {
|
||||||
|
// we handle ENOENT here
|
||||||
|
if (errno != ENOENT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string::size_type pos = path.rfind('/');
|
||||||
|
if (pos == string::npos)
|
||||||
|
// not enough path left?
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!EnsurePathExists(path.substr(0, pos)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// all previous directories should exist at this point
|
||||||
|
return mkdir(path.c_str(), 0755) != -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskModuleCache::IsDir(const string &path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (stat(path.c_str(), &st) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (st.st_mode & S_IFDIR) == S_IFDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
74
src/processor/disk_module_cache.h
Normal file
74
src/processor/disk_module_cache.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright (c) 2007, 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.
|
||||||
|
|
||||||
|
// DiskModuleCache implements SourceLineResolverModuleCacheInterface,
|
||||||
|
// storing the cached objects on disk.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_BREAKPAD_PROCESSOR_DISK_MODULE_CACHE_H__
|
||||||
|
#define GOOGLE_BREAKPAD_PROCESSOR_DISK_MODULE_CACHE_H__
|
||||||
|
|
||||||
|
#include "google_breakpad/processor/source_line_resolver_module_cache_interface.h"
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::istream;
|
||||||
|
using std::ostream;
|
||||||
|
|
||||||
|
class DiskModuleCache : public SourceLineResolverModuleCacheInterface {
|
||||||
|
public:
|
||||||
|
DiskModuleCache(string cache_directory);
|
||||||
|
virtual ~DiskModuleCache() {}
|
||||||
|
|
||||||
|
// Retrieve the symbol data associated with a module
|
||||||
|
virtual bool GetModuleData(const string &symbol_file,
|
||||||
|
istream **data_stream);
|
||||||
|
|
||||||
|
// Get a stream to which the data associated with a module
|
||||||
|
// can be stored
|
||||||
|
virtual bool BeginSetModuleData(const string &symbol_file,
|
||||||
|
ostream **data_stream);
|
||||||
|
// Finish setting the data associated with this module,
|
||||||
|
// data should already have been written to the stream
|
||||||
|
virtual bool EndSetModuleData(const string &symbol_file,
|
||||||
|
ostream **data_stream);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string cache_directory_;
|
||||||
|
// Given a symbol file, map to a cache entry on disk
|
||||||
|
string MapToCacheEntry(const string &symbol_file);
|
||||||
|
// Given a file path, ensure that all directories in the path exist.
|
||||||
|
bool EnsurePathExists(const string &cache_entry);
|
||||||
|
// determine if this path is a directory
|
||||||
|
bool IsDir(const string &path);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // GOOGLE_BREAKPAD_PROCESSOR_DISK_MODULE_CACHE_H__
|
178
src/processor/equals.h
Normal file
178
src/processor/equals.h
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
// Copyright (c) 2007, 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.
|
||||||
|
|
||||||
|
// equals.h: Templatized functions for checking equivalence.
|
||||||
|
//
|
||||||
|
// Use these instead of operator== so that we can check for equivalence
|
||||||
|
// of objects stored as pointers inside linked_ptrs. Equals knows
|
||||||
|
// how to compare certain objects (RangeMap, AddressMap, ContainedRangeMap),
|
||||||
|
// and special-cases linked_ptr as well. It defaults to operator== for
|
||||||
|
// everything else.
|
||||||
|
//
|
||||||
|
// Author: Ted Mielczarek
|
||||||
|
|
||||||
|
#ifndef GOOGLE_BREAKPAD_EQUALS_H_
|
||||||
|
#define GOOGLE_BREAKPAD_EQUALS_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#ifdef __SUNPRO_CC
|
||||||
|
#define BSLR_NO_HASH_MAP
|
||||||
|
#endif // __SUNPRO_CC
|
||||||
|
|
||||||
|
#ifndef BSLR_NO_HASH_MAP
|
||||||
|
#include <ext/hash_map>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||||
|
#include "processor/linked_ptr.h"
|
||||||
|
#include "processor/range_map.h"
|
||||||
|
#include "processor/address_map.h"
|
||||||
|
#include "processor/contained_range_map.h"
|
||||||
|
#include "processor/logging.h"
|
||||||
|
|
||||||
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
#ifndef BSLR_NO_HASH_MAP
|
||||||
|
using __gnu_cxx::hash_map;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In the general case, just use operator==
|
||||||
|
// This should handle base types.
|
||||||
|
template<typename T>
|
||||||
|
inline bool Equals(const T &a, const T &b)
|
||||||
|
{
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for linked_ptr, we want to compare the objects
|
||||||
|
// pointed at, not the raw pointers
|
||||||
|
template<typename U>
|
||||||
|
bool Equals(const linked_ptr<U> &a, const linked_ptr<U> &b)
|
||||||
|
{
|
||||||
|
if (a.get() && b.get())
|
||||||
|
return Equals(*a, *b);
|
||||||
|
|
||||||
|
// if one is NULL, just compare pointers
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for std::map/hash_map, we want to call Equals on each component of
|
||||||
|
// each pair
|
||||||
|
#ifndef BSLR_NO_HASH_MAP
|
||||||
|
template<typename k, typename v>
|
||||||
|
bool Equals(const hash_map<k, v> &a, const hash_map<k, v> &b)
|
||||||
|
{
|
||||||
|
// simple check for equivalent size first
|
||||||
|
if (a.size() != b.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
typename hash_map<k,v>::const_iterator it, found;
|
||||||
|
for (it = a.begin(); it != a.end(); it++) {
|
||||||
|
// if b doesn't contain this entry, then
|
||||||
|
// just get out
|
||||||
|
found = b.find(it->first);
|
||||||
|
if (found == b.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Equals(it->second, found->second))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // BSLR_NO_HASH_MAP
|
||||||
|
|
||||||
|
template<typename k, typename v>
|
||||||
|
bool Equals(const map<k, v> &a, const map<k, v> &b)
|
||||||
|
{
|
||||||
|
// simple check for equivalent size first
|
||||||
|
if (a.size() != b.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
typename map<k,v>::const_iterator it, found;
|
||||||
|
for (it = a.begin(); it != a.end(); it++) {
|
||||||
|
// if b doesn't contain this entry, then
|
||||||
|
// just get out
|
||||||
|
found = b.find(it->first);
|
||||||
|
if (found == b.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Equals(it->second, found->second))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For certain classes we know about, use their Equals method.
|
||||||
|
// Note: a few variations of this are in other places:
|
||||||
|
// processor/basic_source_line_resolver.cc
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
inline bool Equals(const RangeMap<AddressType, EntryType> &a,
|
||||||
|
const RangeMap<AddressType, EntryType> &b)
|
||||||
|
{
|
||||||
|
return a.Equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
inline bool Equals(const typename RangeMap<AddressType, EntryType>::Range &a,
|
||||||
|
const typename RangeMap<AddressType, EntryType>::Range &b)
|
||||||
|
{
|
||||||
|
return a.Equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
inline bool Equals(const AddressMap<AddressType, EntryType> &a,
|
||||||
|
const AddressMap<AddressType, EntryType> &b)
|
||||||
|
{
|
||||||
|
return a.Equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
inline bool Equals(const ContainedRangeMap<AddressType, EntryType> &a,
|
||||||
|
const ContainedRangeMap<AddressType, EntryType> &b)
|
||||||
|
{
|
||||||
|
return a.Equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
inline bool Equals(ContainedRangeMap<AddressType, EntryType> * const &a,
|
||||||
|
ContainedRangeMap<AddressType, EntryType> * const &b)
|
||||||
|
{
|
||||||
|
if (a && b)
|
||||||
|
return a->Equals(*b);
|
||||||
|
|
||||||
|
// if one is NULL, just compare pointer values
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
#endif // GOOGLE_BREAKPAD_EQUALS_H_
|
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||||
#include "google_breakpad/processor/call_stack.h"
|
#include "google_breakpad/processor/call_stack.h"
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
#include "google_breakpad/processor/minidump_processor.h"
|
#include "google_breakpad/processor/minidump_processor.h"
|
||||||
#include "google_breakpad/processor/process_state.h"
|
#include "google_breakpad/processor/process_state.h"
|
||||||
#include "google_breakpad/processor/stack_frame_cpu.h"
|
#include "google_breakpad/processor/stack_frame_cpu.h"
|
||||||
|
#include "processor/disk_module_cache.h"
|
||||||
#include "processor/logging.h"
|
#include "processor/logging.h"
|
||||||
#include "processor/pathname_stripper.h"
|
#include "processor/pathname_stripper.h"
|
||||||
#include "processor/scoped_ptr.h"
|
#include "processor/scoped_ptr.h"
|
||||||
@@ -55,6 +57,7 @@ namespace {
|
|||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using google_breakpad::BasicSourceLineResolver;
|
using google_breakpad::BasicSourceLineResolver;
|
||||||
|
using google_breakpad::DiskModuleCache;
|
||||||
using google_breakpad::CallStack;
|
using google_breakpad::CallStack;
|
||||||
using google_breakpad::CodeModule;
|
using google_breakpad::CodeModule;
|
||||||
using google_breakpad::CodeModules;
|
using google_breakpad::CodeModules;
|
||||||
@@ -433,6 +436,7 @@ static void PrintProcessStateMachineReadable(const ProcessState& process_state)
|
|||||||
// is printed to stdout.
|
// is printed to stdout.
|
||||||
static bool PrintMinidumpProcess(const string &minidump_file,
|
static bool PrintMinidumpProcess(const string &minidump_file,
|
||||||
const vector<string> &symbol_paths,
|
const vector<string> &symbol_paths,
|
||||||
|
const string &symbol_cache_path,
|
||||||
bool machine_readable) {
|
bool machine_readable) {
|
||||||
scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
|
scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
|
||||||
if (!symbol_paths.empty()) {
|
if (!symbol_paths.empty()) {
|
||||||
@@ -440,7 +444,11 @@ static bool PrintMinidumpProcess(const string &minidump_file,
|
|||||||
symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths));
|
symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths));
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicSourceLineResolver resolver;
|
scoped_ptr<DiskModuleCache> disk_cache;
|
||||||
|
if (!symbol_cache_path.empty()) {
|
||||||
|
disk_cache.reset(new DiskModuleCache(symbol_cache_path));
|
||||||
|
}
|
||||||
|
BasicSourceLineResolver resolver(disk_cache.get());
|
||||||
MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver);
|
MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver);
|
||||||
|
|
||||||
// Process the minidump.
|
// Process the minidump.
|
||||||
@@ -463,8 +471,9 @@ static bool PrintMinidumpProcess(const string &minidump_file,
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static void usage(const char *program_name) {
|
static void usage(const char *program_name) {
|
||||||
fprintf(stderr, "usage: %s [-m] <minidump-file> [symbol-path ...]\n"
|
fprintf(stderr, "usage: %s [-m] [-c path] <minidump-file> [symbol-path ...]\n"
|
||||||
" -m : Output in machine-readable format\n",
|
" -m : Output in machine-readable format\n",
|
||||||
|
" -c <path> : Cache symbol files to this path\n",
|
||||||
program_name);
|
program_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,32 +486,48 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *minidump_file;
|
const char *minidump_file;
|
||||||
bool machine_readable;
|
bool machine_readable = false;
|
||||||
int symbol_path_arg;
|
int symbol_path_arg;
|
||||||
|
string symbol_cache_path;
|
||||||
|
|
||||||
if (strcmp(argv[1], "-m") == 0) {
|
// handle switches
|
||||||
if (argc < 3) {
|
int option;
|
||||||
|
opterr = 0;
|
||||||
|
while ((option = getopt(argc, argv, "mc:")) != -1) {
|
||||||
|
switch (option) {
|
||||||
|
case 'm':
|
||||||
|
machine_readable = true;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
symbol_cache_path = optarg;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
if (optopt == 'c')
|
||||||
|
fprintf(stderr, "Error: -c requires an argument.\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Error: unknown option '-%c'.\n", optopt);
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_readable = true;
|
minidump_file = argv[optind];
|
||||||
minidump_file = argv[2];
|
optind++;
|
||||||
symbol_path_arg = 3;
|
|
||||||
} else {
|
|
||||||
machine_readable = false;
|
|
||||||
minidump_file = argv[1];
|
|
||||||
symbol_path_arg = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extra arguments are symbol paths
|
// extra arguments are symbol paths
|
||||||
std::vector<std::string> symbol_paths;
|
std::vector<std::string> symbol_paths;
|
||||||
if (argc > symbol_path_arg) {
|
if (argc > optind) {
|
||||||
for (int argi = symbol_path_arg; argi < argc; ++argi)
|
for (int argi = optind; argi < argc; ++argi)
|
||||||
symbol_paths.push_back(argv[argi]);
|
symbol_paths.push_back(argv[argi]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PrintMinidumpProcess(minidump_file,
|
return PrintMinidumpProcess(minidump_file,
|
||||||
symbol_paths,
|
symbol_paths,
|
||||||
|
symbol_cache_path,
|
||||||
machine_readable) ? 0 : 1;
|
machine_readable) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
61
src/processor/module_serialize_unittest.cc
Normal file
61
src/processor/module_serialize_unittest.cc
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (c) 2007, 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_serialize_unittest.cc: Unit tests for
|
||||||
|
// BasicSourceLineResolver::Module serialization.
|
||||||
|
//
|
||||||
|
// Author: Ted Mielczarek
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
#include "processor/logging.h"
|
||||||
|
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
BPLOG_INIT(&argc, &argv);
|
||||||
|
|
||||||
|
char symbol_test_files[][1024] = {
|
||||||
|
"src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym",
|
||||||
|
"src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; i < sizeof(symbol_test_files) / sizeof(symbol_test_files[0]);
|
||||||
|
i++) {
|
||||||
|
BPLOG(INFO) << "Testing round trip serialize for symbol file "
|
||||||
|
<< symbol_test_files[i];
|
||||||
|
if (!google_breakpad::BasicSourceLineResolver::ModuleRoundTripTest(symbol_test_files[i])) {
|
||||||
|
BPLOG(ERROR) << "FAILED: module round trip test for symbol file "
|
||||||
|
<< symbol_test_files[i];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -40,6 +40,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "processor/range_map.h"
|
#include "processor/range_map.h"
|
||||||
|
#include "processor/equals.h"
|
||||||
#include "processor/logging.h"
|
#include "processor/logging.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -203,6 +204,17 @@ void RangeMap<AddressType, EntryType>::Clear() {
|
|||||||
map_.clear();
|
map_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
bool RangeMap<AddressType, EntryType>::Equals(
|
||||||
|
const RangeMap<AddressType, EntryType> &other) const {
|
||||||
|
return google_breakpad::Equals(map_, other.map_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
bool RangeMap<AddressType, EntryType>::Range::operator==(const Range &other) const {
|
||||||
|
return google_breakpad::Equals(base_, other.base_) &&
|
||||||
|
google_breakpad::Equals(entry_, other.entry_);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
||||||
|
@@ -92,6 +92,8 @@ class RangeMap {
|
|||||||
// initially created.
|
// initially created.
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
bool Equals(const RangeMap<AddressType, EntryType> &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Range {
|
class Range {
|
||||||
public:
|
public:
|
||||||
@@ -101,6 +103,10 @@ class RangeMap {
|
|||||||
AddressType base() const { return base_; }
|
AddressType base() const { return base_; }
|
||||||
EntryType entry() const { return entry_; }
|
EntryType entry() const { return entry_; }
|
||||||
|
|
||||||
|
//XXX: I really wanted this to be Equals, but
|
||||||
|
// I can't seem to get that to work properly.
|
||||||
|
bool operator==(const Range &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The base address of the range. The high address does not need to
|
// The base address of the range. The high address does not need to
|
||||||
// be stored, because RangeMap uses it as the key to the map.
|
// be stored, because RangeMap uses it as the key to the map.
|
||||||
@@ -108,6 +114,8 @@ class RangeMap {
|
|||||||
|
|
||||||
// The entry corresponding to a range.
|
// The entry corresponding to a range.
|
||||||
const EntryType entry_;
|
const EntryType entry_;
|
||||||
|
|
||||||
|
friend class ModuleSerializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convenience types.
|
// Convenience types.
|
||||||
@@ -117,6 +125,11 @@ class RangeMap {
|
|||||||
|
|
||||||
// Maps the high address of each range to a EntryType.
|
// Maps the high address of each range to a EntryType.
|
||||||
AddressToRangeMap map_;
|
AddressToRangeMap map_;
|
||||||
|
|
||||||
|
friend class ModuleSerializer;
|
||||||
|
|
||||||
|
//template<typename T>
|
||||||
|
//friend bool Equals(const T &a, const T &b);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "processor/simple_symbol_supplier.h"
|
#include "processor/simple_symbol_supplier.h"
|
||||||
|
@@ -100,11 +100,23 @@ struct StackFrameInfo {
|
|||||||
program_string.erase();
|
program_string.erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(const StackFrameInfo &other) const {
|
||||||
|
return valid == other.valid &&
|
||||||
|
prolog_size == other.prolog_size &&
|
||||||
|
epilog_size == other.epilog_size &&
|
||||||
|
parameter_size == other.parameter_size &&
|
||||||
|
saved_register_size == other.saved_register_size &&
|
||||||
|
local_size == other.local_size &&
|
||||||
|
max_stack_size == other.max_stack_size &&
|
||||||
|
allocates_base_pointer == other.allocates_base_pointer &&
|
||||||
|
program_string == other.program_string;
|
||||||
|
}
|
||||||
|
|
||||||
// Identifies which fields in the structure are valid. This is of
|
// Identifies which fields in the structure are valid. This is of
|
||||||
// type Validity, but it is defined as an int because it's not
|
// type Validity, but it is defined as an int because it's not
|
||||||
// possible to OR values into an enumerated type. Users must check
|
// possible to OR values into an enumerated type. Users must check
|
||||||
// this field before using any other.
|
// this field before using any other.
|
||||||
int valid;
|
u_int32_t valid;
|
||||||
|
|
||||||
// These values come from IDiaFrameData.
|
// These values come from IDiaFrameData.
|
||||||
u_int32_t prolog_size;
|
u_int32_t prolog_size;
|
||||||
|
Reference in New Issue
Block a user