Introduce microdump_stackwalk comand line executable

This introduces the microdump_stackwalk binary which takes advantage
of the MicrodumpProcessor to symbolize microdumps.
Its operation is identical to the one of minidump_stackwalk.
This CL, in fact, is also refactoring most of the common bits into
stackwalk_common.

BUG=chromium:410294
R=mmandlis@chromium.org

Review URL: https://breakpad.appspot.com/4704002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1405 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
primiano@chromium.org 2014-11-25 11:36:38 +00:00
parent be21ad8190
commit 57e5b074f6
10 changed files with 1508 additions and 750 deletions

View file

@ -301,6 +301,7 @@ src_third_party_libdisasm_libdisasm_a_SOURCES = \
## Programs
bin_PROGRAMS += \
src/processor/microdump_stackwalk \
src/processor/minidump_dump \
src/processor/minidump_stackwalk
endif !DISABLE_PROCESSOR
@ -375,6 +376,8 @@ endif !DISABLE_PROCESSOR
if !DISABLE_PROCESSOR
check_SCRIPTS = \
src/processor/microdump_stackwalk_test \
src/processor/microdump_stackwalk_machine_readable_test \
src/processor/minidump_dump_test \
src/processor/minidump_stackwalk_test \
src/processor/minidump_stackwalk_machine_readable_test
@ -710,10 +713,10 @@ src_processor_exploitability_unittest_LDADD = \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -802,10 +805,10 @@ src_processor_microdump_processor_unittest_LDADD = \
src/processor/source_line_resolver_base.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -844,10 +847,10 @@ src_processor_minidump_processor_unittest_LDADD = \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -976,10 +979,10 @@ src_processor_stackwalker_selftest_LDADD = \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -1130,6 +1133,40 @@ src_processor_minidump_dump_LDADD = \
src/processor/minidump.o \
src/processor/pathname_stripper.o
src_processor_microdump_stackwalk_SOURCES = \
src/processor/microdump_stackwalk.cc
src_processor_microdump_stackwalk_LDADD = \
src/processor/basic_code_modules.o \
src/processor/basic_source_line_resolver.o \
src/processor/binarystream.o \
src/processor/call_stack.o \
src/processor/cfi_frame_info.o \
src/processor/disassembler_x86.o \
src/processor/dump_context.o \
src/processor/dump_object.o \
src/processor/logging.o \
src/processor/microdump.o \
src/processor/microdump_processor.o \
src/processor/pathname_stripper.o \
src/processor/process_state.o \
src/processor/simple_symbol_supplier.o \
src/processor/source_line_resolver_base.o \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalk_common.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
src/processor/stackwalker_sparc.o \
src/processor/stackwalker_x86.o \
src/processor/tokenize.o \
src/third_party/libdisasm/libdisasm.a
src_processor_minidump_stackwalk_SOURCES = \
src/processor/minidump_stackwalk.cc
src_processor_minidump_stackwalk_LDADD = \
@ -1153,11 +1190,12 @@ src_processor_minidump_stackwalk_LDADD = \
src/processor/source_line_resolver_base.o \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalk_common.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \

View file

@ -145,6 +145,7 @@ check_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext.S
@DISABLE_PROCESSOR_FALSE@am__append_11 = \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk
@ -516,7 +517,7 @@ am__src_third_party_libdisasm_libdisasm_a_SOURCES_DIST = \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.$(OBJEXT)
src_third_party_libdisasm_libdisasm_a_OBJECTS = \
$(am_src_third_party_libdisasm_libdisasm_a_OBJECTS)
@DISABLE_PROCESSOR_FALSE@am__EXEEXT_1 = \
@DISABLE_PROCESSOR_FALSE@am__EXEEXT_1 = src/processor/microdump_stackwalk$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk$(EXEEXT)
@LINUX_HOST_TRUE@am__EXEEXT_2 = src/client/linux/linux_dumper_unittest_helper$(EXEEXT)
@ -852,10 +853,10 @@ src_processor_exploitability_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -923,10 +924,10 @@ src_processor_microdump_processor_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -935,6 +936,42 @@ src_processor_microdump_processor_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
am__src_processor_microdump_stackwalk_SOURCES_DIST = \
src/processor/microdump_stackwalk.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_microdump_stackwalk_OBJECTS = src/processor/microdump_stackwalk.$(OBJEXT)
src_processor_microdump_stackwalk_OBJECTS = \
$(am_src_processor_microdump_stackwalk_OBJECTS)
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_DEPENDENCIES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.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/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
am__src_processor_minidump_dump_SOURCES_DIST = \
src/processor/minidump_dump.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_dump_OBJECTS = src/processor/minidump_dump.$(OBJEXT)
@ -976,10 +1013,10 @@ src_processor_minidump_processor_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -1015,11 +1052,12 @@ src_processor_minidump_stackwalk_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -1185,10 +1223,10 @@ src_processor_stackwalker_selftest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -1440,6 +1478,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \
$(src_processor_fast_source_line_resolver_unittest_SOURCES) \
$(src_processor_map_serializers_unittest_SOURCES) \
$(src_processor_microdump_processor_unittest_SOURCES) \
$(src_processor_microdump_stackwalk_SOURCES) \
$(src_processor_minidump_dump_SOURCES) \
$(src_processor_minidump_processor_unittest_SOURCES) \
$(src_processor_minidump_stackwalk_SOURCES) \
@ -1484,6 +1523,7 @@ DIST_SOURCES = \
$(am__src_processor_fast_source_line_resolver_unittest_SOURCES_DIST) \
$(am__src_processor_map_serializers_unittest_SOURCES_DIST) \
$(am__src_processor_microdump_processor_unittest_SOURCES_DIST) \
$(am__src_processor_microdump_stackwalk_SOURCES_DIST) \
$(am__src_processor_minidump_dump_SOURCES_DIST) \
$(am__src_processor_minidump_processor_unittest_SOURCES_DIST) \
$(am__src_processor_minidump_stackwalk_SOURCES_DIST) \
@ -2053,6 +2093,8 @@ lib_LIBRARIES = $(am__append_5) $(am__append_8)
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.h
@DISABLE_PROCESSOR_FALSE@check_SCRIPTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk_machine_readable_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk_machine_readable_test
@ -2370,10 +2412,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2470,10 +2512,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2514,10 +2556,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2660,10 +2702,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2826,6 +2868,41 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk.cc
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_LDADD = \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.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/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk.cc
@ -2850,11 +2927,12 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -3849,6 +3927,13 @@ src/testing/src/src_processor_microdump_processor_unittest-gmock-all.$(OBJEXT):
src/processor/microdump_processor_unittest$(EXEEXT): $(src_processor_microdump_processor_unittest_OBJECTS) $(src_processor_microdump_processor_unittest_DEPENDENCIES) $(EXTRA_src_processor_microdump_processor_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/microdump_processor_unittest$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_microdump_processor_unittest_OBJECTS) $(src_processor_microdump_processor_unittest_LDADD) $(LIBS)
src/processor/microdump_stackwalk.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/microdump_stackwalk$(EXEEXT): $(src_processor_microdump_stackwalk_OBJECTS) $(src_processor_microdump_stackwalk_DEPENDENCIES) $(EXTRA_src_processor_microdump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/microdump_stackwalk$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_microdump_stackwalk_OBJECTS) $(src_processor_microdump_stackwalk_LDADD) $(LIBS)
src/processor/minidump_dump.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
@ -4384,6 +4469,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump_processor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump_stackwalk.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Po@am__quote@
@ -7539,6 +7625,20 @@ src/processor/stackwalker_selftest.log: src/processor/stackwalker_selftest$(EXEE
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
src/processor/microdump_stackwalk_test.log: src/processor/microdump_stackwalk_test
@p='src/processor/microdump_stackwalk_test'; \
b='src/processor/microdump_stackwalk_test'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
src/processor/microdump_stackwalk_machine_readable_test.log: src/processor/microdump_stackwalk_machine_readable_test
@p='src/processor/microdump_stackwalk_machine_readable_test'; \
b='src/processor/microdump_stackwalk_machine_readable_test'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
src/processor/minidump_dump_test.log: src/processor/minidump_dump_test
@p='src/processor/minidump_dump_test'; \
b='src/processor/minidump_dump_test'; \

View file

@ -0,0 +1,151 @@
// Copyright (c) 2014 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.
// microdump_stackwalk.cc: Process a microdump with MicrodumpProcessor, printing
// the results, including stack traces.
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <string>
#include <vector>
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/microdump_processor.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stack_frame_symbolizer.h"
#include "processor/logging.h"
#include "processor/simple_symbol_supplier.h"
#include "processor/stackwalk_common.h"
namespace {
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::MicrodumpProcessor;
using google_breakpad::ProcessResult;
using google_breakpad::ProcessState;
using google_breakpad::scoped_ptr;
using google_breakpad::SimpleSymbolSupplier;
using google_breakpad::StackFrameSymbolizer;
// Processes |microdump_file| using MicrodumpProcessor. |symbol_path|, if
// non-empty, is the base directory of a symbol storage area, laid out in
// the format required by SimpleSymbolSupplier. If such a storage area
// is specified, it is made available for use by the MicrodumpProcessor.
//
// Returns the value of MicrodumpProcessor::Process. If processing succeeds,
// prints identifying OS and CPU information from the microdump, crash
// information and call stacks for the crashing thread.
// All information is printed to stdout.
int PrintMicrodumpProcess(const char* microdump_file,
const std::vector<string>& symbol_paths,
bool machine_readable) {
std::ifstream file_stream(microdump_file);
std::vector<char> bytes;
file_stream.seekg(0, std::ios_base::end);
bytes.resize(file_stream.tellg());
file_stream.seekg(0, std::ios_base::beg);
file_stream.read(&bytes[0], bytes.size());
string microdump_content(&bytes[0], bytes.size());
scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
if (!symbol_paths.empty()) {
symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths));
}
BasicSourceLineResolver resolver;
StackFrameSymbolizer frame_symbolizer(symbol_supplier.get(), &resolver);
ProcessState process_state;
MicrodumpProcessor microdump_processor(&frame_symbolizer);
ProcessResult res = microdump_processor.Process(microdump_content,
&process_state);
if (res == google_breakpad::PROCESS_OK) {
if (machine_readable) {
PrintProcessStateMachineReadable(process_state);
} else {
PrintProcessState(process_state);
}
return 0;
}
BPLOG(ERROR) << "MicrodumpProcessor::Process failed (code = " << res << ")";
return 1;
}
void usage(const char *program_name) {
fprintf(stderr, "usage: %s [-m] <microdump-file> [symbol-path ...]\n"
" -m : Output in machine-readable format\n",
program_name);
}
} // namespace
int main(int argc, char** argv) {
BPLOG_INIT(&argc, &argv);
if (argc < 2) {
usage(argv[0]);
return 1;
}
const char* microdump_file;
bool machine_readable;
int symbol_path_arg;
if (strcmp(argv[1], "-m") == 0) {
if (argc < 3) {
usage(argv[0]);
return 1;
}
machine_readable = true;
microdump_file = argv[2];
symbol_path_arg = 3;
} else {
machine_readable = false;
microdump_file = argv[1];
symbol_path_arg = 2;
}
// extra arguments are symbol paths
std::vector<string> symbol_paths;
if (argc > symbol_path_arg) {
for (int argi = symbol_path_arg; argi < argc; ++argi)
symbol_paths.push_back(argv[argi]);
}
return PrintMicrodumpProcess(microdump_file,
symbol_paths,
machine_readable);
}

View file

@ -0,0 +1,37 @@
#!/bin/sh
# Copyright (c) 2014, 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.
testdata_dir=$srcdir/src/processor/testdata
./src/processor/microdump_stackwalk -m $testdata_dir/microdump.dmp \
$testdata_dir/symbols/microdump | \
tr -d '\015' | \
diff -u $testdata_dir/microdump.stackwalk.machine_readable.out -
exit $?

View file

@ -0,0 +1,37 @@
#!/bin/sh
# Copyright (c) 2014, 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.
testdata_dir=$srcdir/src/processor/testdata
./src/processor/microdump_stackwalk $testdata_dir/microdump.dmp \
$testdata_dir/symbols/microdump | \
tr -d '\015' | \
diff -u $testdata_dir/microdump.stackwalk.out -
exit $?

View file

@ -33,7 +33,6 @@
// Author: Mark Mentovai
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
@ -42,744 +41,20 @@
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/code_modules.h"
#include "google_breakpad/processor/minidump.h"
#include "google_breakpad/processor/minidump_processor.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/logging.h"
#include "processor/pathname_stripper.h"
#include "processor/simple_symbol_supplier.h"
#include "processor/stackwalk_common.h"
namespace {
using std::vector;
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::CodeModules;
using google_breakpad::MinidumpModule;
using google_breakpad::MinidumpProcessor;
using google_breakpad::PathnameStripper;
using google_breakpad::ProcessState;
using google_breakpad::scoped_ptr;
using google_breakpad::SimpleSymbolSupplier;
using google_breakpad::StackFrame;
using google_breakpad::StackFramePPC;
using google_breakpad::StackFrameSPARC;
using google_breakpad::StackFrameX86;
using google_breakpad::StackFrameAMD64;
using google_breakpad::StackFrameARM;
using google_breakpad::StackFrameARM64;
using google_breakpad::StackFrameMIPS;
// Separator character for machine readable output.
static const char kOutputSeparator = '|';
// PrintRegister prints a register's name and value to stdout. It will
// print four registers on a line. For the first register in a set,
// pass 0 for |start_col|. For registers in a set, pass the most recent
// return value of PrintRegister.
// The caller is responsible for printing the final newline after a set
// of registers is completely printed, regardless of the number of calls
// to PrintRegister.
static const int kMaxWidth = 80; // optimize for an 80-column terminal
static int PrintRegister(const char *name, uint32_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// PrintRegister64 does the same thing, but for 64-bit registers.
static int PrintRegister64(const char *name, uint64_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// StripSeparator takes a string |original| and returns a copy
// of the string with all occurences of |kOutputSeparator| removed.
static string StripSeparator(const string &original) {
string result = original;
string::size_type position = 0;
while ((position = result.find(kOutputSeparator, position)) != string::npos) {
result.erase(position, 1);
}
position = 0;
while ((position = result.find('\n', position)) != string::npos) {
result.erase(position, 1);
}
return result;
}
// PrintStack prints the call stack in |stack| to stdout, in a reasonably
// useful form. Module, function, and source file names are displayed if
// they are available. The code offset to the base code address of the
// source line, function, or module is printed, preferring them in that
// order. If no source line, function, or module information is available,
// an absolute code offset is printed.
//
// If |cpu| is a recognized CPU name, relevant register state for each stack
// frame printed is also output, if available.
static void PrintStack(const CallStack *stack, const string &cpu) {
int frame_count = stack->frames()->size();
if (frame_count == 0) {
printf(" <no frames>\n");
}
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%2d ", frame_index);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
printf("%s", PathnameStripper::File(frame->module->code_file()).c_str());
if (!frame->function_name.empty()) {
printf("!%s", frame->function_name.c_str());
if (!frame->source_file_name.empty()) {
string source_file = PathnameStripper::File(frame->source_file_name);
printf(" [%s : %d + 0x%" PRIx64 "]",
source_file.c_str(),
frame->source_line,
instruction_address - frame->source_line_base);
} else {
printf(" + 0x%" PRIx64, instruction_address - frame->function_base);
}
} else {
printf(" + 0x%" PRIx64,
instruction_address - frame->module->base_address());
}
} else {
printf("0x%" PRIx64, instruction_address);
}
printf("\n ");
int sequence = 0;
if (cpu == "x86") {
const StackFrameX86 *frame_x86 =
reinterpret_cast<const StackFrameX86*>(frame);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
}
} else if (cpu == "ppc") {
const StackFramePPC *frame_ppc =
reinterpret_cast<const StackFramePPC*>(frame);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
} else if (cpu == "amd64") {
const StackFrameAMD64 *frame_amd64 =
reinterpret_cast<const StackFrameAMD64*>(frame);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX)
sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX)
sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX)
sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX)
sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI)
sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI)
sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8)
sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9)
sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10)
sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11)
sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12)
sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13)
sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14)
sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15)
sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence);
} else if (cpu == "sparc") {
const StackFrameSPARC *frame_sparc =
reinterpret_cast<const StackFrameSPARC*>(frame);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
} else if (cpu == "arm") {
const StackFrameARM *frame_arm =
reinterpret_cast<const StackFrameARM*>(frame);
// Argument registers (caller-saves), which will likely only be valid
// for the youngest frame.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0)
sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1)
sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2)
sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3)
sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence);
// General-purpose callee-saves registers.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5)
sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6)
sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7)
sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8)
sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9)
sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10)
sequence = PrintRegister("r10", frame_arm->context.iregs[10], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12)
sequence = PrintRegister("r12", frame_arm->context.iregs[12], sequence);
// Registers with a dedicated or conventional purpose.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_arm->context.iregs[11], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_arm->context.iregs[13], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR)
sequence = PrintRegister("lr", frame_arm->context.iregs[14], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
} else if (cpu == "arm64") {
const StackFrameARM64 *frame_arm64 =
reinterpret_cast<const StackFrameARM64*>(frame);
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) {
sequence =
PrintRegister64("x0", frame_arm64->context.iregs[0], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) {
sequence =
PrintRegister64("x1", frame_arm64->context.iregs[1], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) {
sequence =
PrintRegister64("x2", frame_arm64->context.iregs[2], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) {
sequence =
PrintRegister64("x3", frame_arm64->context.iregs[3], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) {
sequence =
PrintRegister64("x4", frame_arm64->context.iregs[4], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) {
sequence =
PrintRegister64("x5", frame_arm64->context.iregs[5], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) {
sequence =
PrintRegister64("x6", frame_arm64->context.iregs[6], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) {
sequence =
PrintRegister64("x7", frame_arm64->context.iregs[7], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) {
sequence =
PrintRegister64("x8", frame_arm64->context.iregs[8], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) {
sequence =
PrintRegister64("x9", frame_arm64->context.iregs[9], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X10) {
sequence =
PrintRegister64("x10", frame_arm64->context.iregs[10], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X11) {
sequence =
PrintRegister64("x11", frame_arm64->context.iregs[11], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X12) {
sequence =
PrintRegister64("x12", frame_arm64->context.iregs[12], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X13) {
sequence =
PrintRegister64("x13", frame_arm64->context.iregs[13], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X14) {
sequence =
PrintRegister64("x14", frame_arm64->context.iregs[14], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X15) {
sequence =
PrintRegister64("x15", frame_arm64->context.iregs[15], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X16) {
sequence =
PrintRegister64("x16", frame_arm64->context.iregs[16], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X17) {
sequence =
PrintRegister64("x17", frame_arm64->context.iregs[17], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X18) {
sequence =
PrintRegister64("x18", frame_arm64->context.iregs[18], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X19) {
sequence =
PrintRegister64("x19", frame_arm64->context.iregs[19], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X20) {
sequence =
PrintRegister64("x20", frame_arm64->context.iregs[20], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X21) {
sequence =
PrintRegister64("x21", frame_arm64->context.iregs[21], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X22) {
sequence =
PrintRegister64("x22", frame_arm64->context.iregs[22], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X23) {
sequence =
PrintRegister64("x23", frame_arm64->context.iregs[23], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X24) {
sequence =
PrintRegister64("x24", frame_arm64->context.iregs[24], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X25) {
sequence =
PrintRegister64("x25", frame_arm64->context.iregs[25], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X26) {
sequence =
PrintRegister64("x26", frame_arm64->context.iregs[26], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X27) {
sequence =
PrintRegister64("x27", frame_arm64->context.iregs[27], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X28) {
sequence =
PrintRegister64("x28", frame_arm64->context.iregs[28], sequence);
}
// Registers with a dedicated or conventional purpose.
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) {
sequence =
PrintRegister64("fp", frame_arm64->context.iregs[29], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) {
sequence =
PrintRegister64("lr", frame_arm64->context.iregs[30], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) {
sequence =
PrintRegister64("sp", frame_arm64->context.iregs[31], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) {
sequence =
PrintRegister64("pc", frame_arm64->context.iregs[32], sequence);
}
} else if (cpu == "mips") {
const StackFrameMIPS* frame_mips =
reinterpret_cast<const StackFrameMIPS*>(frame);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP)
sequence = PrintRegister64("gp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP)
sequence = PrintRegister64("sp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP)
sequence = PrintRegister64("fp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA)
sequence = PrintRegister64("ra",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC)
sequence = PrintRegister64("pc", frame_mips->context.epc, sequence);
// Save registers s0-s7
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0)
sequence = PrintRegister64("s0",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1)
sequence = PrintRegister64("s1",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2)
sequence = PrintRegister64("s2",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3)
sequence = PrintRegister64("s3",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4)
sequence = PrintRegister64("s4",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5)
sequence = PrintRegister64("s5",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6)
sequence = PrintRegister64("s6",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7)
sequence = PrintRegister64("s7",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7],
sequence);
}
printf("\n Found by: %s\n", frame->trust_description().c_str());
}
}
// PrintStackMachineReadable prints the call stack in |stack| to stdout,
// in the following machine readable pipe-delimited text format:
// thread number|frame number|module|function|source file|line|offset
//
// Module, function, source file, and source line may all be empty
// depending on availability. The code offset follows the same rules as
// PrintStack above.
static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
int frame_count = stack->frames()->size();
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index,
kOutputSeparator);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
assert(!frame->module->code_file().empty());
printf("%s", StripSeparator(PathnameStripper::File(
frame->module->code_file())).c_str());
if (!frame->function_name.empty()) {
printf("%c%s", kOutputSeparator,
StripSeparator(frame->function_name).c_str());
if (!frame->source_file_name.empty()) {
printf("%c%s%c%d%c0x%" PRIx64,
kOutputSeparator,
StripSeparator(frame->source_file_name).c_str(),
kOutputSeparator,
frame->source_line,
kOutputSeparator,
instruction_address - frame->source_line_base);
} else {
printf("%c%c%c0x%" PRIx64,
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->function_base);
}
} else {
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->module->base_address());
}
} else {
// the printf before this prints a trailing separator for module name
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address);
}
printf("\n");
}
}
// ContainsModule checks whether a given |module| is in the vector
// |modules_without_symbols|.
static bool ContainsModule(
const vector<const CodeModule*> *modules,
const CodeModule *module) {
assert(modules);
assert(module);
vector<const CodeModule*>::const_iterator iter;
for (iter = modules->begin(); iter != modules->end(); ++iter) {
if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
return true;
}
}
return false;
}
// PrintModule prints a single |module| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModule(
const CodeModule *module,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols,
uint64_t main_address) {
string symbol_issues;
if (ContainsModule(modules_without_symbols, module)) {
symbol_issues = " (WARNING: No symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
} else if (ContainsModule(modules_with_corrupt_symbols, module)) {
symbol_issues = " (WARNING: Corrupt symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
}
uint64_t base_address = module->base_address();
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
main_address != 0 && base_address == main_address ? " (main)" : "",
symbol_issues.c_str());
}
// PrintModules prints the list of all loaded |modules| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModules(
const CodeModules *modules,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols) {
if (!modules)
return;
printf("\n");
printf("Loaded modules:\n");
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols,
main_address);
}
}
// PrintModulesMachineReadable outputs a list of loaded modules,
// one per line, in the following machine-readable pipe-delimited
// text format:
// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}|
// {Base Address}|{Max Address}|{Main}
static void PrintModulesMachineReadable(const CodeModules *modules) {
if (!modules)
return;
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
uint64_t base_address = module->base_address();
printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
kOutputSeparator, StripSeparator(module->version()).c_str(),
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->debug_file())).c_str(),
kOutputSeparator,
StripSeparator(module->debug_identifier()).c_str(),
kOutputSeparator, base_address,
kOutputSeparator, base_address + module->size() - 1,
kOutputSeparator,
main_module != NULL && base_address == main_address ? 1 : 0);
}
}
static void PrintProcessState(const ProcessState& process_state) {
// Print OS and CPU information.
string cpu = process_state.system_info()->cpu;
string cpu_info = process_state.system_info()->cpu_info;
printf("Operating system: %s\n", process_state.system_info()->os.c_str());
printf(" %s\n",
process_state.system_info()->os_version.c_str());
printf("CPU: %s\n", cpu.c_str());
if (!cpu_info.empty()) {
// This field is optional.
printf(" %s\n", cpu_info.c_str());
}
printf(" %d CPU%s\n",
process_state.system_info()->cpu_count,
process_state.system_info()->cpu_count != 1 ? "s" : "");
printf("\n");
// Print crash information.
if (process_state.crashed()) {
printf("Crash reason: %s\n", process_state.crash_reason().c_str());
printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
} else {
printf("No crash\n");
}
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("Assertion: %s\n", assertion.c_str());
}
// If the thread that requested the dump is known, print it first.
int requesting_thread = process_state.requesting_thread();
if (requesting_thread != -1) {
printf("\n");
printf("Thread %d (%s)\n",
requesting_thread,
process_state.crashed() ? "crashed" :
"requested dump, did not crash");
PrintStack(process_state.threads()->at(requesting_thread), cpu);
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// Don't print the crash thread again, it was already printed.
printf("\n");
printf("Thread %d\n", thread_index);
PrintStack(process_state.threads()->at(thread_index), cpu);
}
}
PrintModules(process_state.modules(),
process_state.modules_without_symbols(),
process_state.modules_with_corrupt_symbols());
}
static void PrintProcessStateMachineReadable(const ProcessState& process_state)
{
// Print OS and CPU information.
// OS|{OS Name}|{OS Version}
// CPU|{CPU Name}|{CPU Info}|{Number of CPUs}
printf("OS%c%s%c%s\n", kOutputSeparator,
StripSeparator(process_state.system_info()->os).c_str(),
kOutputSeparator,
StripSeparator(process_state.system_info()->os_version).c_str());
printf("CPU%c%s%c%s%c%d\n", kOutputSeparator,
StripSeparator(process_state.system_info()->cpu).c_str(),
kOutputSeparator,
// this may be empty
StripSeparator(process_state.system_info()->cpu_info).c_str(),
kOutputSeparator,
process_state.system_info()->cpu_count);
int requesting_thread = process_state.requesting_thread();
// Print crash information.
// Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
printf("Crash%c", kOutputSeparator);
if (process_state.crashed()) {
printf("%s%c0x%" PRIx64 "%c",
StripSeparator(process_state.crash_reason()).c_str(),
kOutputSeparator, process_state.crash_address(), kOutputSeparator);
} else {
// print assertion info, if available, in place of crash reason,
// instead of the unhelpful "No crash"
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("%s%c%c", StripSeparator(assertion).c_str(),
kOutputSeparator, kOutputSeparator);
} else {
printf("No crash%c%c", kOutputSeparator, kOutputSeparator);
}
}
if (requesting_thread != -1) {
printf("%d\n", requesting_thread);
} else {
printf("\n");
}
PrintModulesMachineReadable(process_state.modules());
// blank line to indicate start of threads
printf("\n");
// If the thread that requested the dump is known, print it first.
if (requesting_thread != -1) {
PrintStackMachineReadable(requesting_thread,
process_state.threads()->at(requesting_thread));
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// Don't print the crash thread again, it was already printed.
PrintStackMachineReadable(thread_index,
process_state.threads()->at(thread_index));
}
}
}
using google_breakpad::scoped_ptr;
// Processes |minidump_file| using MinidumpProcessor. |symbol_path|, if
// non-empty, is the base directory of a symbol storage area, laid out in
@ -791,9 +66,9 @@ static void PrintProcessStateMachineReadable(const ProcessState& process_state)
// information if the minidump was produced as a result of a crash, and
// call stacks for each thread contained in the minidump. All information
// is printed to stdout.
static bool PrintMinidumpProcess(const string &minidump_file,
const vector<string> &symbol_paths,
bool machine_readable) {
bool PrintMinidumpProcess(const string &minidump_file,
const std::vector<string> &symbol_paths,
bool machine_readable) {
scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
if (!symbol_paths.empty()) {
// TODO(mmentovai): check existence of symbol_path if specified?
@ -820,14 +95,14 @@ static bool PrintMinidumpProcess(const string &minidump_file,
return true;
}
} // namespace
static void usage(const char *program_name) {
void usage(const char *program_name) {
fprintf(stderr, "usage: %s [-m] <minidump-file> [symbol-path ...]\n"
" -m : Output in machine-readable format\n",
program_name);
}
} // namespace
int main(int argc, char **argv) {
BPLOG_INIT(&argc, &argv);

View file

@ -0,0 +1,767 @@
// 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.
// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
// executables to print the content of dumps (w/ stack traces) on the console.
//
// Author: Mark Mentovai
#include "processor/stackwalk_common.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include "common/using_std_string.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/code_modules.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/logging.h"
#include "processor/pathname_stripper.h"
namespace google_breakpad {
namespace {
using std::vector;
// Separator character for machine readable output.
static const char kOutputSeparator = '|';
// PrintRegister prints a register's name and value to stdout. It will
// print four registers on a line. For the first register in a set,
// pass 0 for |start_col|. For registers in a set, pass the most recent
// return value of PrintRegister.
// The caller is responsible for printing the final newline after a set
// of registers is completely printed, regardless of the number of calls
// to PrintRegister.
static const int kMaxWidth = 80; // optimize for an 80-column terminal
static int PrintRegister(const char *name, uint32_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// PrintRegister64 does the same thing, but for 64-bit registers.
static int PrintRegister64(const char *name, uint64_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// StripSeparator takes a string |original| and returns a copy
// of the string with all occurences of |kOutputSeparator| removed.
static string StripSeparator(const string &original) {
string result = original;
string::size_type position = 0;
while ((position = result.find(kOutputSeparator, position)) != string::npos) {
result.erase(position, 1);
}
position = 0;
while ((position = result.find('\n', position)) != string::npos) {
result.erase(position, 1);
}
return result;
}
// PrintStack prints the call stack in |stack| to stdout, in a reasonably
// useful form. Module, function, and source file names are displayed if
// they are available. The code offset to the base code address of the
// source line, function, or module is printed, preferring them in that
// order. If no source line, function, or module information is available,
// an absolute code offset is printed.
//
// If |cpu| is a recognized CPU name, relevant register state for each stack
// frame printed is also output, if available.
static void PrintStack(const CallStack *stack, const string &cpu) {
int frame_count = stack->frames()->size();
if (frame_count == 0) {
printf(" <no frames>\n");
}
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%2d ", frame_index);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
printf("%s", PathnameStripper::File(frame->module->code_file()).c_str());
if (!frame->function_name.empty()) {
printf("!%s", frame->function_name.c_str());
if (!frame->source_file_name.empty()) {
string source_file = PathnameStripper::File(frame->source_file_name);
printf(" [%s : %d + 0x%" PRIx64 "]",
source_file.c_str(),
frame->source_line,
instruction_address - frame->source_line_base);
} else {
printf(" + 0x%" PRIx64, instruction_address - frame->function_base);
}
} else {
printf(" + 0x%" PRIx64,
instruction_address - frame->module->base_address());
}
} else {
printf("0x%" PRIx64, instruction_address);
}
printf("\n ");
int sequence = 0;
if (cpu == "x86") {
const StackFrameX86 *frame_x86 =
reinterpret_cast<const StackFrameX86*>(frame);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
}
} else if (cpu == "ppc") {
const StackFramePPC *frame_ppc =
reinterpret_cast<const StackFramePPC*>(frame);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
} else if (cpu == "amd64") {
const StackFrameAMD64 *frame_amd64 =
reinterpret_cast<const StackFrameAMD64*>(frame);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX)
sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX)
sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX)
sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX)
sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI)
sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI)
sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8)
sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9)
sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10)
sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11)
sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12)
sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13)
sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14)
sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15)
sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence);
} else if (cpu == "sparc") {
const StackFrameSPARC *frame_sparc =
reinterpret_cast<const StackFrameSPARC*>(frame);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
} else if (cpu == "arm") {
const StackFrameARM *frame_arm =
reinterpret_cast<const StackFrameARM*>(frame);
// Argument registers (caller-saves), which will likely only be valid
// for the youngest frame.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0)
sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1)
sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2)
sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3)
sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence);
// General-purpose callee-saves registers.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5)
sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6)
sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7)
sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8)
sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9)
sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10)
sequence = PrintRegister("r10", frame_arm->context.iregs[10], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12)
sequence = PrintRegister("r12", frame_arm->context.iregs[12], sequence);
// Registers with a dedicated or conventional purpose.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_arm->context.iregs[11], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_arm->context.iregs[13], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR)
sequence = PrintRegister("lr", frame_arm->context.iregs[14], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
} else if (cpu == "arm64") {
const StackFrameARM64 *frame_arm64 =
reinterpret_cast<const StackFrameARM64*>(frame);
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) {
sequence =
PrintRegister64("x0", frame_arm64->context.iregs[0], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) {
sequence =
PrintRegister64("x1", frame_arm64->context.iregs[1], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) {
sequence =
PrintRegister64("x2", frame_arm64->context.iregs[2], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) {
sequence =
PrintRegister64("x3", frame_arm64->context.iregs[3], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) {
sequence =
PrintRegister64("x4", frame_arm64->context.iregs[4], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) {
sequence =
PrintRegister64("x5", frame_arm64->context.iregs[5], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) {
sequence =
PrintRegister64("x6", frame_arm64->context.iregs[6], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) {
sequence =
PrintRegister64("x7", frame_arm64->context.iregs[7], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) {
sequence =
PrintRegister64("x8", frame_arm64->context.iregs[8], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) {
sequence =
PrintRegister64("x9", frame_arm64->context.iregs[9], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X10) {
sequence =
PrintRegister64("x10", frame_arm64->context.iregs[10], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X11) {
sequence =
PrintRegister64("x11", frame_arm64->context.iregs[11], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X12) {
sequence =
PrintRegister64("x12", frame_arm64->context.iregs[12], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X13) {
sequence =
PrintRegister64("x13", frame_arm64->context.iregs[13], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X14) {
sequence =
PrintRegister64("x14", frame_arm64->context.iregs[14], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X15) {
sequence =
PrintRegister64("x15", frame_arm64->context.iregs[15], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X16) {
sequence =
PrintRegister64("x16", frame_arm64->context.iregs[16], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X17) {
sequence =
PrintRegister64("x17", frame_arm64->context.iregs[17], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X18) {
sequence =
PrintRegister64("x18", frame_arm64->context.iregs[18], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X19) {
sequence =
PrintRegister64("x19", frame_arm64->context.iregs[19], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X20) {
sequence =
PrintRegister64("x20", frame_arm64->context.iregs[20], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X21) {
sequence =
PrintRegister64("x21", frame_arm64->context.iregs[21], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X22) {
sequence =
PrintRegister64("x22", frame_arm64->context.iregs[22], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X23) {
sequence =
PrintRegister64("x23", frame_arm64->context.iregs[23], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X24) {
sequence =
PrintRegister64("x24", frame_arm64->context.iregs[24], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X25) {
sequence =
PrintRegister64("x25", frame_arm64->context.iregs[25], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X26) {
sequence =
PrintRegister64("x26", frame_arm64->context.iregs[26], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X27) {
sequence =
PrintRegister64("x27", frame_arm64->context.iregs[27], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X28) {
sequence =
PrintRegister64("x28", frame_arm64->context.iregs[28], sequence);
}
// Registers with a dedicated or conventional purpose.
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) {
sequence =
PrintRegister64("fp", frame_arm64->context.iregs[29], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) {
sequence =
PrintRegister64("lr", frame_arm64->context.iregs[30], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) {
sequence =
PrintRegister64("sp", frame_arm64->context.iregs[31], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) {
sequence =
PrintRegister64("pc", frame_arm64->context.iregs[32], sequence);
}
} else if (cpu == "mips") {
const StackFrameMIPS* frame_mips =
reinterpret_cast<const StackFrameMIPS*>(frame);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP)
sequence = PrintRegister64("gp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP)
sequence = PrintRegister64("sp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP)
sequence = PrintRegister64("fp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA)
sequence = PrintRegister64("ra",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC)
sequence = PrintRegister64("pc", frame_mips->context.epc, sequence);
// Save registers s0-s7
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0)
sequence = PrintRegister64("s0",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1)
sequence = PrintRegister64("s1",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2)
sequence = PrintRegister64("s2",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3)
sequence = PrintRegister64("s3",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4)
sequence = PrintRegister64("s4",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5)
sequence = PrintRegister64("s5",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6)
sequence = PrintRegister64("s6",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7)
sequence = PrintRegister64("s7",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7],
sequence);
}
printf("\n Found by: %s\n", frame->trust_description().c_str());
}
}
// PrintStackMachineReadable prints the call stack in |stack| to stdout,
// in the following machine readable pipe-delimited text format:
// thread number|frame number|module|function|source file|line|offset
//
// Module, function, source file, and source line may all be empty
// depending on availability. The code offset follows the same rules as
// PrintStack above.
static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
int frame_count = stack->frames()->size();
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index,
kOutputSeparator);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
assert(!frame->module->code_file().empty());
printf("%s", StripSeparator(PathnameStripper::File(
frame->module->code_file())).c_str());
if (!frame->function_name.empty()) {
printf("%c%s", kOutputSeparator,
StripSeparator(frame->function_name).c_str());
if (!frame->source_file_name.empty()) {
printf("%c%s%c%d%c0x%" PRIx64,
kOutputSeparator,
StripSeparator(frame->source_file_name).c_str(),
kOutputSeparator,
frame->source_line,
kOutputSeparator,
instruction_address - frame->source_line_base);
} else {
printf("%c%c%c0x%" PRIx64,
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->function_base);
}
} else {
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->module->base_address());
}
} else {
// the printf before this prints a trailing separator for module name
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address);
}
printf("\n");
}
}
// ContainsModule checks whether a given |module| is in the vector
// |modules_without_symbols|.
static bool ContainsModule(
const vector<const CodeModule*> *modules,
const CodeModule *module) {
assert(modules);
assert(module);
vector<const CodeModule*>::const_iterator iter;
for (iter = modules->begin(); iter != modules->end(); ++iter) {
if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
return true;
}
}
return false;
}
// PrintModule prints a single |module| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModule(
const CodeModule *module,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols,
uint64_t main_address) {
string symbol_issues;
if (ContainsModule(modules_without_symbols, module)) {
symbol_issues = " (WARNING: No symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
} else if (ContainsModule(modules_with_corrupt_symbols, module)) {
symbol_issues = " (WARNING: Corrupt symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
}
uint64_t base_address = module->base_address();
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
main_address != 0 && base_address == main_address ? " (main)" : "",
symbol_issues.c_str());
}
// PrintModules prints the list of all loaded |modules| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModules(
const CodeModules *modules,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols) {
if (!modules)
return;
printf("\n");
printf("Loaded modules:\n");
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols,
main_address);
}
}
// PrintModulesMachineReadable outputs a list of loaded modules,
// one per line, in the following machine-readable pipe-delimited
// text format:
// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}|
// {Base Address}|{Max Address}|{Main}
static void PrintModulesMachineReadable(const CodeModules *modules) {
if (!modules)
return;
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
uint64_t base_address = module->base_address();
printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
kOutputSeparator, StripSeparator(module->version()).c_str(),
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->debug_file())).c_str(),
kOutputSeparator,
StripSeparator(module->debug_identifier()).c_str(),
kOutputSeparator, base_address,
kOutputSeparator, base_address + module->size() - 1,
kOutputSeparator,
main_module != NULL && base_address == main_address ? 1 : 0);
}
}
} // namespace
void PrintProcessState(const ProcessState& process_state) {
// Print OS and CPU information.
string cpu = process_state.system_info()->cpu;
string cpu_info = process_state.system_info()->cpu_info;
printf("Operating system: %s\n", process_state.system_info()->os.c_str());
printf(" %s\n",
process_state.system_info()->os_version.c_str());
printf("CPU: %s\n", cpu.c_str());
if (!cpu_info.empty()) {
// This field is optional.
printf(" %s\n", cpu_info.c_str());
}
printf(" %d CPU%s\n",
process_state.system_info()->cpu_count,
process_state.system_info()->cpu_count != 1 ? "s" : "");
printf("\n");
// Print crash information.
if (process_state.crashed()) {
printf("Crash reason: %s\n", process_state.crash_reason().c_str());
printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
} else {
printf("No crash\n");
}
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("Assertion: %s\n", assertion.c_str());
}
// If the thread that requested the dump is known, print it first.
int requesting_thread = process_state.requesting_thread();
if (requesting_thread != -1) {
printf("\n");
printf("Thread %d (%s)\n",
requesting_thread,
process_state.crashed() ? "crashed" :
"requested dump, did not crash");
PrintStack(process_state.threads()->at(requesting_thread), cpu);
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// Don't print the crash thread again, it was already printed.
printf("\n");
printf("Thread %d\n", thread_index);
PrintStack(process_state.threads()->at(thread_index), cpu);
}
}
PrintModules(process_state.modules(),
process_state.modules_without_symbols(),
process_state.modules_with_corrupt_symbols());
}
void PrintProcessStateMachineReadable(const ProcessState& process_state) {
// Print OS and CPU information.
// OS|{OS Name}|{OS Version}
// CPU|{CPU Name}|{CPU Info}|{Number of CPUs}
printf("OS%c%s%c%s\n", kOutputSeparator,
StripSeparator(process_state.system_info()->os).c_str(),
kOutputSeparator,
StripSeparator(process_state.system_info()->os_version).c_str());
printf("CPU%c%s%c%s%c%d\n", kOutputSeparator,
StripSeparator(process_state.system_info()->cpu).c_str(),
kOutputSeparator,
// this may be empty
StripSeparator(process_state.system_info()->cpu_info).c_str(),
kOutputSeparator,
process_state.system_info()->cpu_count);
int requesting_thread = process_state.requesting_thread();
// Print crash information.
// Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
printf("Crash%c", kOutputSeparator);
if (process_state.crashed()) {
printf("%s%c0x%" PRIx64 "%c",
StripSeparator(process_state.crash_reason()).c_str(),
kOutputSeparator, process_state.crash_address(), kOutputSeparator);
} else {
// print assertion info, if available, in place of crash reason,
// instead of the unhelpful "No crash"
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("%s%c%c", StripSeparator(assertion).c_str(),
kOutputSeparator, kOutputSeparator);
} else {
printf("No crash%c%c", kOutputSeparator, kOutputSeparator);
}
}
if (requesting_thread != -1) {
printf("%d\n", requesting_thread);
} else {
printf("\n");
}
PrintModulesMachineReadable(process_state.modules());
// blank line to indicate start of threads
printf("\n");
// If the thread that requested the dump is known, print it first.
if (requesting_thread != -1) {
PrintStackMachineReadable(requesting_thread,
process_state.threads()->at(requesting_thread));
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// Don't print the crash thread again, it was already printed.
PrintStackMachineReadable(thread_index,
process_state.threads()->at(thread_index));
}
}
}
} // namespace google_breakpad

View file

@ -0,0 +1,46 @@
// 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.
// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
// executables to print the content of dumps (w/ stack traces) on the console.
#ifndef PROCESSOR_STACKWALK_COMMON_H__
#define PROCESSOR_STACKWALK_COMMON_H__
namespace google_breakpad {
class ProcessState;
void PrintProcessStateMachineReadable(const ProcessState& process_state);
void PrintProcessState(const ProcessState& process_state);
} // namespace google_breakpad
#endif // PROCESSOR_STACKWALK_COMMON_H__

View file

@ -0,0 +1,129 @@
OS||
CPU|||0
Crash||0x0|0
Module|libchromeshell.so||libchromeshell.so|76304586D0CD2C8FF899C602BF1756A20|0x987ab000|0x9b359fff|0
Module|RELRO:libchromeshell.so||RELRO:libchromeshell.so|000000000000000000000000000000000|0x9b35a000|0x9b4b5fff|0
Module|libchromeshell.so||libchromeshell.so|000000000000000000000000000000000|0x9b4b6000|0x9b4cbfff|0
Module|libchromium_android_linker.so||libchromium_android_linker.so|AC480D966558562B46D4583A55D904E60|0xa47a3000|0xa47b3fff|0
Module|libwebviewchromium_loader.so||libwebviewchromium_loader.so|932CC9935B065A05D39E38681E0A5F2E0|0xac35d000|0xac35ffff|0
Module|libandroid.so||libandroid.so|E2C6CBE7D4588EF8111B01903B27FEA80|0xac360000|0xac36ffff|0
Module|libGLESv2_adreno.so||libGLESv2_adreno.so|83D249BAACD2F2C10C13B70C1F64252C0|0xac370000|0xac4b1fff|0
Module|libGLESv1_CM_adreno.so||libGLESv1_CM_adreno.so|58A32EAAFDADB17139F988E96B860C8E0|0xac4b3000|0xac4e6fff|0
Module|libgsl.so||libgsl.so|C71008FE91C209D6D5E9EA5DBB44BF080|0xac4e7000|0xac51afff|0
Module|libEGL_adreno.so||libEGL_adreno.so|134B50AAA945C8C16B0021DF014AA6150|0xac51b000|0xac544fff|0
Module|libjavacrypto.so||libjavacrypto.so|9D372357993C7650365479A34E676E290|0xace37000|0xace4efff|0
Module|librs_jni.so||librs_jni.so|0D2147262F4305E3AED211CB96FC96BA0|0xace4f000|0xace57fff|0
Module|libaudioeffect_jni.so||libaudioeffect_jni.so|3F276EEAE72C2C9FC768FF2E482957510|0xace58000|0xace5dfff|0
Module|libsoundpool.so||libsoundpool.so|CDA9BA072D4DECC71C5E63467275E7EE0|0xace5e000|0xace61fff|0
Module|libstagefright_amrnb_common.so||libstagefright_amrnb_common.so|D02CB251CF8787A770DE2CFDC52A2B040|0xace62000|0xace6ffff|0
Module|libvorbisidec.so||libvorbisidec.so|F59669C665FE4B073886A8DAAECEA86F0|0xace70000|0xace8afff|0
Module|libstagefright_yuv.so||libstagefright_yuv.so|9FC00D0B150FE9FC57763A76206D1D550|0xace8b000|0xace8efff|0
Module|libstagefright_omx.so||libstagefright_omx.so|C2D6408786A8582A0EAE64D047577F800|0xace90000|0xaceaefff|0
Module|libstagefright_enc_common.so||libstagefright_enc_common.so|E11DA546CE9E08D1D647E8E1135DAD810|0xaceaf000|0xaceb1fff|0
Module|libstagefright_avc_common.so||libstagefright_avc_common.so|741CC494F5299870A1C62FD71E37AE5F0|0xaceb2000|0xaceb8fff|0
Module|libpowermanager.so||libpowermanager.so|D3EA22EB9F383751AB500AE5951F0DB30|0xaceb9000|0xacebdfff|0
Module|libopus.so||libopus.so|F19A7DFF3B6F3AF94EAE23CA21905BAD0|0xacebe000|0xacef9fff|0
Module|libdrmframework.so||libdrmframework.so|87AFCC5E47ED503148F1AA03777E88590|0xacefa000|0xacf14fff|0
Module|libstagefright.so||libstagefright.so|A0D663218D972496B104B7B9FF0727BD0|0xacf16000|0xad029fff|0
Module|libmtp.so||libmtp.so|55B5F5E024DB37CABEC6A8F31DD950870|0xad02a000|0xad03ffff|0
Module|libjhead.so||libjhead.so|D2AB743CCCD8D2EB9B66A47707CC1E530|0xad040000|0xad04afff|0
Module|libexif.so||libexif.so|4D1E2F0F58012FABA091A21E4CEEFFE20|0xad04c000|0xad077fff|0
Module|libmedia_jni.so||libmedia_jni.so|20D19E07A0CA5B5790EEB83C8F6915570|0xad078000|0xad0b3fff|0
Module|libjnigraphics.so||libjnigraphics.so|8FF5949AE957364C270D0F448DAD4FE20|0xafe8a000|0xafe8cfff|0
Module|libcompiler_rt.so||libcompiler_rt.so|F2B1298EE4C6EA0900CDACD17FB5C16B0|0xafe8d000|0xafe94fff|0
Module|libadreno_utils.so||libadreno_utils.so|37FA52E92BF716E0268B9619EE8D61630|0xafe95000|0xafe98fff|0
Module|memtrack.msm8960.so||memtrack.msm8960.so|F36630BD0C6DC4B52A0E5D5D57BE682A0|0xafe9b000|0xafe9dfff|0
Module|libjavacore.so||libjavacore.so|FE4EB304B0639D600DFB5871136831C50|0xb15ab000|0xb15e2fff|0
Module|libbacktrace_libc++.so||libbacktrace_libc++.so|CF0326786BDECFB45A519C7005E851000|0xb4fc8000|0xb4fd0fff|0
Module|libart.so||libart.so|3E343A5B3F9534F5E40AD9BEAC46C8E80|0xb4fd2000|0xb52d5fff|0
Module|libusbhost.so||libusbhost.so|3CBDF0DE27B9554508AD60FDC96CBC620|0xb52f9000|0xb52fcfff|0
Module|libssl.so||libssl.so|36F280D15D51F4EEFA92279E8BBD84360|0xb52fd000|0xb533dfff|0
Module|libsqlite.so||libsqlite.so|D02DDA779C053EF3CC279A1E1789C4250|0xb533e000|0xb539cfff|0
Module|libsoundtrigger.so||libsoundtrigger.so|F954BA248E12C9AF32F54434F977FEF80|0xb539e000|0xb53acfff|0
Module|libselinux.so||libselinux.so|125671BDF56FEE67902BE338575373000|0xb53ad000|0xb53bafff|0
Module|libprocessgroup.so||libprocessgroup.so|4E6C8C876BA563C3C4B0B3BA562093920|0xb53bb000|0xb53befff|0
Module|libpdfium.so||libpdfium.so|83C5B450634DDB5C4FC41CA61A35B3740|0xb53bf000|0xb5819fff|0
Module|libnetd_client.so||libnetd_client.so|56B149396A4DAF176E26B4A85DA87BF30|0xb581f000|0xb5822fff|0
Module|libnativehelper.so||libnativehelper.so|A20D742D5BF711D12587563B5C4BF64A0|0xb5823000|0xb5829fff|0
Module|libnativebridge.so||libnativebridge.so|495F8887F27909EE1E3E69A657E0A9AB0|0xb582a000|0xb582dfff|0
Module|libminikin.so||libminikin.so|31B45FE1FA6CC789F945332C6FECF9750|0xb582e000|0xb5839fff|0
Module|libmemtrack.so||libmemtrack.so|CCA8BE0D07D24523C8D02FEE5F724EA70|0xb583a000|0xb583cfff|0
Module|libstagefright_foundation.so||libstagefright_foundation.so|60A6E0B998632198B80EB0941121CD710|0xb583d000|0xb5851fff|0
Module|libsonivox.so||libsonivox.so|6E42AB0836D73C21533C08A98EE7B24C0|0xb5852000|0xb58a2fff|0
Module|libcommon_time_client.so||libcommon_time_client.so|E43E7FA869E4BCDAA3CC9601DF5A6A520|0xb58a8000|0xb58b6fff|0
Module|libnbaio.so||libnbaio.so|C84019C90BCA7E95A773B5A75A460D880|0xb58b7000|0xb58c0fff|0
Module|libmedia.so||libmedia.so|895A37F76D93E51B0ED7E90E5B71A9330|0xb58c1000|0xb595afff|0
Module|libinputflinger.so||libinputflinger.so|C5323479053FDA41E355482925A30D120|0xb595b000|0xb5996fff|0
Module|libinput.so||libinput.so|74F168649BE8583159D23A6406D107740|0xb5997000|0xb59b1fff|0
Module|libimg_utils.so||libimg_utils.so|41712F8718C430707F8CEE5532CB59200|0xb59b2000|0xb59c0fff|0
Module|libjpeg.so||libjpeg.so|89A4F06810290EEAF309C12642A3ECFA0|0xb59c1000|0xb59f2fff|0
Module|libskia.so||libskia.so|65E6AAFD915FB244BFE6BE6C4E5E3EC40|0xb59f4000|0xb5c22fff|0
Module|libRScpp.so||libRScpp.so|23FBB5490C5DBF1E99CD76AC2AA151410|0xb5c28000|0xb5c44fff|0
Module|libpng.so||libpng.so|3BFE44EFE288C7A1AD7BE317B9F1BDBC0|0xb5c45000|0xb5c6cfff|0
Module|libft2.so||libft2.so|659F1470013A04F7702E4BAB65F034E70|0xb5c6d000|0xb5cc6fff|0
Module|libbcinfo.so||libbcinfo.so|FB93884C5EC21F71C68861C20993EB6C0|0xb5cc7000|0xb5d03fff|0
Module|libbcc.so||libbcc.so|21B734672A14ED6267B966640C16823E0|0xb5d04000|0xb5d26fff|0
Module|libc++.so||libc++.so|BE6F28596E6CE20F5E49A9E0BC824DA00|0xb5d47000|0xb5ddafff|0
Module|libLLVM.so||libLLVM.so|377A25164D6ACDC0F7A38F5E378EC8670|0xb5ddd000|0xb6714fff|0
Module|libRS.so||libRS.so|8D7E15A890FAF52D874044C9F02C6D130|0xb671c000|0xb6755fff|0
Module|libhwui.so||libhwui.so|670166E37528A7F183D1B05F52020ABD0|0xb6756000|0xb67a1fff|0
Module|libicuuc.so||libicuuc.so|1B1FD653750DE88B86D7E83095EE37160|0xb67a2000|0xb68b1fff|0
Module|libgabi++.so||libgabi++.so|F4F99E4A6E63BF8C8005D96B2BAC8CEB0|0xb68b6000|0xb68bbfff|0
Module|libicui18n.so||libicui18n.so|237F53C12084A7F42405B410FDE8B4020|0xb68bc000|0xb6a22fff|0
Module|libharfbuzz_ng.so||libharfbuzz_ng.so|AC5AE16EC01F4362C8E63DF66565090D0|0xb6a23000|0xb6a6afff|0
Module|libwpa_client.so||libwpa_client.so|254351EC49125FE3A72F78EAB38381410|0xb6a6b000|0xb6a6ffff|0
Module|libnetutils.so||libnetutils.so|F8BA9819E3B7FA0BE155985B6C09FC570|0xb6a70000|0xb6a76fff|0
Module|libhardware_legacy.so||libhardware_legacy.so|C08391F010B5A32265D4D781325FFCEE0|0xb6a77000|0xb6a7cfff|0
Module|libexpat.so||libexpat.so|B98E65710C415C83E972EBDC1EB52AC00|0xb6a7e000|0xb6a94fff|0
Module|libcrypto.so||libcrypto.so|E26A420F0A5BCD2AC04E9B7B19F67C3D0|0xb6a95000|0xb6b96fff|0
Module|libhardware.so||libhardware.so|914425D16565257955F7E1574360B71F0|0xb6b99000|0xb6b9bfff|0
Module|libui.so||libui.so|4F3E1A188AE72585AF4278E4FA5266730|0xb6b9c000|0xb6ba7fff|0
Module|libsync.so||libsync.so|2D9083CB8C22C02E1412DA13B1CA43AE0|0xb6ba8000|0xb6baafff|0
Module|libgui.so||libgui.so|559E784386AC5E53A9D4D7F9916AA7F90|0xb6bab000|0xb6bf9fff|0
Module|libcamera_metadata.so||libcamera_metadata.so|D8696CD80D9B725AFEA007DFCE2562E60|0xb6bfa000|0xb6c01fff|0
Module|libcamera_client.so||libcamera_client.so|116B760482930C77445ABAC1A3276D0B0|0xb6c02000|0xb6c3bfff|0
Module|libspeexresampler.so||libspeexresampler.so|AC1D054A26491BE96E8BCCB1E5F2926F0|0xb6c3c000|0xb6c41fff|0
Module|libaudioutils.so||libaudioutils.so|D330B25521C028B95D7E9360F7C6D6510|0xb6c42000|0xb6c47fff|0
Module|libz.so||libz.so|03AD92B0BEDAA751C0016E97AE374CAE0|0xb6c48000|0xb6c61fff|0
Module|libbinder.so||libbinder.so|AC6C388A36224541CD74B35818111B760|0xb6c62000|0xb6c91fff|0
Module|libandroidfw.so||libandroidfw.so|102764B5F4D4D6F6F1A0C7360182BDEE0|0xb6c92000|0xb6cb9fff|0
Module|libGLESv2.so||libGLESv2.so|E2F67EE50006FD0ED1482E1463C5CCFF0|0xb6cba000|0xb6cc4fff|0
Module|libGLESv1_CM.so||libGLESv1_CM.so|EFE6AB19F4060BCECF8CF0E68958C2F60|0xb6cc5000|0xb6ccbfff|0
Module|libETC1.so||libETC1.so|C91EAF69D18F0D499BD58532BBA173690|0xb6ccc000|0xb6ccffff|0
Module|libunwind-ptrace.so||libunwind-ptrace.so|7AE0C00FAEDEA3E81109CC784D49A6960|0xb6cd0000|0xb6cd3fff|0
Module|libunwind.so||libunwind.so|EF89B10946BDF6079AAF789F56192FDA0|0xb6cd4000|0xb6ce1fff|0
Module|libgccdemangle.so||libgccdemangle.so|3874D35A672DF92604963290963F44990|0xb6d28000|0xb6d2efff|0
Module|libbacktrace.so||libbacktrace.so|45B51BF91D330E793C9142C2617D7A8E0|0xb6d31000|0xb6d38fff|0
Module|libutils.so||libutils.so|4939CC7D9325757DDAB52A218D55F4720|0xb6d3a000|0xb6d51fff|0
Module|libstlport.so||libstlport.so|2FE003E5119C67BABE1A9FAB459A5A5D0|0xb6d52000|0xb6d8cfff|0
Module|libcutils.so||libcutils.so|8AE85E0A2B96C0006F4BC72D01BDB7BD0|0xb6d8d000|0xb6d99fff|0
Module|libGLES_trace.so||libGLES_trace.so|A12BAF7D82BE28EC681730452D351E880|0xb6d9b000|0xb6e0bfff|0
Module|libEGL.so||libEGL.so|924D4C5446BF1132A902C15519E5C4FD0|0xb6e0c000|0xb6e73fff|0
Module|libandroid_runtime.so||libandroid_runtime.so|EE75A142ED1607624B6579D4590DD7CB0|0xb6e77000|0xb6f52fff|0
Module|libstdc++.so||libstdc++.so|DFCD7772F3A5BD1E84A50C4DBFDE6F570|0xb6f53000|0xb6f56fff|0
Module|libm.so||libm.so|AE3467401278371A956801500FC8187D0|0xb6f57000|0xb6f6ffff|0
Module|liblog.so||liblog.so|0A492DEF82842051996A468D87F23F010|0xb6f71000|0xb6f77fff|0
Module|libc.so||libc.so|10EC186B04E97F6A24DAA891779479380|0xb6f79000|0xb6fd2fff|0
Module|libsigchain.so||libsigchain.so|D773C773634B82249E887ECBC5D28C900|0xb6fdd000|0xb6fdffff|0
0|0|libchromeshell.so|content::::CrashIntentionally|/s/chrome-brkpad/src/out/Debug/../../content/renderer/render_frame_impl.cc|267|0x2
0|1|libchromeshell.so|content::::MaybeHandleDebugURL|/s/chrome-brkpad/src/out/Debug/../../content/renderer/render_frame_impl.cc|310|0x3
0|2|libchromeshell.so|content::RenderFrameImpl::PrepareRenderViewForNavigation|/s/chrome-brkpad/src/out/Debug/../../content/renderer/render_frame_impl.cc|4008|0x3
0|3|libchromeshell.so|content::RenderFrameImpl::OnNavigate|/s/chrome-brkpad/src/out/Debug/../../content/renderer/render_frame_impl.cc|936|0x1f
0|4|libchromeshell.so|content::RenderFrameImpl::OnMessageReceived|/s/chrome-brkpad/src/out/Debug/../../base/tuple.h|548|0x7
0|5|libchromeshell.so|content::MessageRouter::RouteMessage|/s/chrome-brkpad/src/out/Debug/../../content/common/message_router.cc|54|0x7
0|6|libchromeshell.so|content::ChildThread::OnMessageReceived|/s/chrome-brkpad/src/out/Debug/../../content/child/child_thread.cc|502|0x9
0|7|libchromeshell.so|IPC::ChannelProxy::Context::OnDispatchMessage|/s/chrome-brkpad/src/out/Debug/../../ipc/ipc_channel_proxy.cc|274|0x9
0|8|libchromeshell.so|base::debug::TaskAnnotator::RunTask|/s/chrome-brkpad/src/out/Debug/../../base/callback.h|401|0x5
0|9|libchromeshell.so|base::MessageLoop::RunTask|/s/chrome-brkpad/src/out/Debug/../../base/message_loop/message_loop.cc|447|0x11
0|10|libchromeshell.so|base::MessageLoop::DeferOrRunPendingTask|/s/chrome-brkpad/src/out/Debug/../../base/message_loop/message_loop.cc|456|0x7
0|11|libchromeshell.so|base::MessageLoop::DoWork|/s/chrome-brkpad/src/out/Debug/../../base/message_loop/message_loop.cc|565|0x7
0|12|libchromeshell.so|base::MessagePumpDefault::Run|/s/chrome-brkpad/src/out/Debug/../../base/message_loop/message_pump_default.cc|32|0x7
0|13|libchromeshell.so|base::MessageLoop::RunHandler|/s/chrome-brkpad/src/out/Debug/../../base/message_loop/message_loop.cc|415|0x5
0|14|libchromeshell.so|base::RunLoop::Run|/s/chrome-brkpad/src/out/Debug/../../base/run_loop.cc|54|0x5
0|15|libchromeshell.so|base::MessageLoop::Run|/s/chrome-brkpad/src/out/Debug/../../base/message_loop/message_loop.cc|308|0x5
0|16|libchromeshell.so|content::RendererMain|/s/chrome-brkpad/src/out/Debug/../../content/renderer/renderer_main.cc|235|0x3
0|17|libchromeshell.so|content::RunNamedProcessTypeMain|/s/chrome-brkpad/src/out/Debug/../../content/app/content_main_runner.cc|423|0xb
0|18|libchromeshell.so|content::ContentMainRunnerImpl::Run|/s/chrome-brkpad/src/out/Debug/../../content/app/content_main_runner.cc|789|0x3
0|19|libchromeshell.so|content::Start|/s/chrome-brkpad/src/out/Debug/../../content/app/android/content_main.cc|48|0x3
0|20|||||0xa4d56459

View file

@ -0,0 +1,178 @@
Operating system:
CPU:
0 CPUs
Crash reason:
Crash address: 0x0
Thread 0 (crashed)
0 libchromeshell.so!content::::CrashIntentionally [render_frame_impl.cc : 267 + 0x2]
Found by: given as instruction pointer in context
1 libchromeshell.so!content::::MaybeHandleDebugURL [render_frame_impl.cc : 310 + 0x3]
Found by: call frame info
2 libchromeshell.so!content::RenderFrameImpl::PrepareRenderViewForNavigation [render_frame_impl.cc : 4008 + 0x3]
Found by: call frame info
3 libchromeshell.so!content::RenderFrameImpl::OnNavigate [render_frame_impl.cc : 936 + 0x1f]
Found by: call frame info
4 libchromeshell.so!content::RenderFrameImpl::OnMessageReceived [tuple.h : 548 + 0x7]
Found by: call frame info
5 libchromeshell.so!content::MessageRouter::RouteMessage [message_router.cc : 54 + 0x7]
Found by: call frame info
6 libchromeshell.so!content::ChildThread::OnMessageReceived [child_thread.cc : 502 + 0x9]
Found by: call frame info
7 libchromeshell.so!IPC::ChannelProxy::Context::OnDispatchMessage [ipc_channel_proxy.cc : 274 + 0x9]
Found by: call frame info
8 libchromeshell.so!base::debug::TaskAnnotator::RunTask [callback.h : 401 + 0x5]
Found by: call frame info
9 libchromeshell.so!base::MessageLoop::RunTask [message_loop.cc : 447 + 0x11]
Found by: call frame info
10 libchromeshell.so!base::MessageLoop::DeferOrRunPendingTask [message_loop.cc : 456 + 0x7]
Found by: call frame info
11 libchromeshell.so!base::MessageLoop::DoWork [message_loop.cc : 565 + 0x7]
Found by: call frame info
12 libchromeshell.so!base::MessagePumpDefault::Run [message_pump_default.cc : 32 + 0x7]
Found by: call frame info
13 libchromeshell.so!base::MessageLoop::RunHandler [message_loop.cc : 415 + 0x5]
Found by: call frame info
14 libchromeshell.so!base::RunLoop::Run [run_loop.cc : 54 + 0x5]
Found by: call frame info
15 libchromeshell.so!base::MessageLoop::Run [message_loop.cc : 308 + 0x5]
Found by: call frame info
16 libchromeshell.so!content::RendererMain [renderer_main.cc : 235 + 0x3]
Found by: call frame info
17 libchromeshell.so!content::RunNamedProcessTypeMain [content_main_runner.cc : 423 + 0xb]
Found by: call frame info
18 libchromeshell.so!content::ContentMainRunnerImpl::Run [content_main_runner.cc : 789 + 0x3]
Found by: call frame info
19 libchromeshell.so!content::Start [content_main.cc : 48 + 0x3]
Found by: call frame info
20 0xa4d56459
Found by: call frame info
Loaded modules:
0x987ab000 - 0x9b359fff libchromeshell.so ???
0x9b35a000 - 0x9b4b5fff RELRO:libchromeshell.so ???
0x9b4b6000 - 0x9b4cbfff libchromeshell.so ???
0xa47a3000 - 0xa47b3fff libchromium_android_linker.so ???
0xac35d000 - 0xac35ffff libwebviewchromium_loader.so ???
0xac360000 - 0xac36ffff libandroid.so ???
0xac370000 - 0xac4b1fff libGLESv2_adreno.so ???
0xac4b3000 - 0xac4e6fff libGLESv1_CM_adreno.so ???
0xac4e7000 - 0xac51afff libgsl.so ???
0xac51b000 - 0xac544fff libEGL_adreno.so ???
0xace37000 - 0xace4efff libjavacrypto.so ???
0xace4f000 - 0xace57fff librs_jni.so ???
0xace58000 - 0xace5dfff libaudioeffect_jni.so ???
0xace5e000 - 0xace61fff libsoundpool.so ???
0xace62000 - 0xace6ffff libstagefright_amrnb_common.so ???
0xace70000 - 0xace8afff libvorbisidec.so ???
0xace8b000 - 0xace8efff libstagefright_yuv.so ???
0xace90000 - 0xaceaefff libstagefright_omx.so ???
0xaceaf000 - 0xaceb1fff libstagefright_enc_common.so ???
0xaceb2000 - 0xaceb8fff libstagefright_avc_common.so ???
0xaceb9000 - 0xacebdfff libpowermanager.so ???
0xacebe000 - 0xacef9fff libopus.so ???
0xacefa000 - 0xacf14fff libdrmframework.so ???
0xacf16000 - 0xad029fff libstagefright.so ???
0xad02a000 - 0xad03ffff libmtp.so ???
0xad040000 - 0xad04afff libjhead.so ???
0xad04c000 - 0xad077fff libexif.so ???
0xad078000 - 0xad0b3fff libmedia_jni.so ???
0xafe8a000 - 0xafe8cfff libjnigraphics.so ???
0xafe8d000 - 0xafe94fff libcompiler_rt.so ???
0xafe95000 - 0xafe98fff libadreno_utils.so ???
0xafe9b000 - 0xafe9dfff memtrack.msm8960.so ???
0xb15ab000 - 0xb15e2fff libjavacore.so ???
0xb4fc8000 - 0xb4fd0fff libbacktrace_libc++.so ???
0xb4fd2000 - 0xb52d5fff libart.so ???
0xb52f9000 - 0xb52fcfff libusbhost.so ???
0xb52fd000 - 0xb533dfff libssl.so ???
0xb533e000 - 0xb539cfff libsqlite.so ???
0xb539e000 - 0xb53acfff libsoundtrigger.so ???
0xb53ad000 - 0xb53bafff libselinux.so ???
0xb53bb000 - 0xb53befff libprocessgroup.so ???
0xb53bf000 - 0xb5819fff libpdfium.so ???
0xb581f000 - 0xb5822fff libnetd_client.so ???
0xb5823000 - 0xb5829fff libnativehelper.so ???
0xb582a000 - 0xb582dfff libnativebridge.so ???
0xb582e000 - 0xb5839fff libminikin.so ???
0xb583a000 - 0xb583cfff libmemtrack.so ???
0xb583d000 - 0xb5851fff libstagefright_foundation.so ???
0xb5852000 - 0xb58a2fff libsonivox.so ???
0xb58a8000 - 0xb58b6fff libcommon_time_client.so ???
0xb58b7000 - 0xb58c0fff libnbaio.so ???
0xb58c1000 - 0xb595afff libmedia.so ???
0xb595b000 - 0xb5996fff libinputflinger.so ???
0xb5997000 - 0xb59b1fff libinput.so ???
0xb59b2000 - 0xb59c0fff libimg_utils.so ???
0xb59c1000 - 0xb59f2fff libjpeg.so ???
0xb59f4000 - 0xb5c22fff libskia.so ???
0xb5c28000 - 0xb5c44fff libRScpp.so ???
0xb5c45000 - 0xb5c6cfff libpng.so ???
0xb5c6d000 - 0xb5cc6fff libft2.so ???
0xb5cc7000 - 0xb5d03fff libbcinfo.so ???
0xb5d04000 - 0xb5d26fff libbcc.so ???
0xb5d47000 - 0xb5ddafff libc++.so ???
0xb5ddd000 - 0xb6714fff libLLVM.so ???
0xb671c000 - 0xb6755fff libRS.so ???
0xb6756000 - 0xb67a1fff libhwui.so ???
0xb67a2000 - 0xb68b1fff libicuuc.so ???
0xb68b6000 - 0xb68bbfff libgabi++.so ???
0xb68bc000 - 0xb6a22fff libicui18n.so ???
0xb6a23000 - 0xb6a6afff libharfbuzz_ng.so ???
0xb6a6b000 - 0xb6a6ffff libwpa_client.so ???
0xb6a70000 - 0xb6a76fff libnetutils.so ???
0xb6a77000 - 0xb6a7cfff libhardware_legacy.so ???
0xb6a7e000 - 0xb6a94fff libexpat.so ???
0xb6a95000 - 0xb6b96fff libcrypto.so ???
0xb6b99000 - 0xb6b9bfff libhardware.so ???
0xb6b9c000 - 0xb6ba7fff libui.so ???
0xb6ba8000 - 0xb6baafff libsync.so ???
0xb6bab000 - 0xb6bf9fff libgui.so ???
0xb6bfa000 - 0xb6c01fff libcamera_metadata.so ???
0xb6c02000 - 0xb6c3bfff libcamera_client.so ???
0xb6c3c000 - 0xb6c41fff libspeexresampler.so ???
0xb6c42000 - 0xb6c47fff libaudioutils.so ???
0xb6c48000 - 0xb6c61fff libz.so ???
0xb6c62000 - 0xb6c91fff libbinder.so ???
0xb6c92000 - 0xb6cb9fff libandroidfw.so ???
0xb6cba000 - 0xb6cc4fff libGLESv2.so ???
0xb6cc5000 - 0xb6ccbfff libGLESv1_CM.so ???
0xb6ccc000 - 0xb6ccffff libETC1.so ???
0xb6cd0000 - 0xb6cd3fff libunwind-ptrace.so ???
0xb6cd4000 - 0xb6ce1fff libunwind.so ???
0xb6d28000 - 0xb6d2efff libgccdemangle.so ???
0xb6d31000 - 0xb6d38fff libbacktrace.so ???
0xb6d3a000 - 0xb6d51fff libutils.so ???
0xb6d52000 - 0xb6d8cfff libstlport.so ???
0xb6d8d000 - 0xb6d99fff libcutils.so ???
0xb6d9b000 - 0xb6e0bfff libGLES_trace.so ???
0xb6e0c000 - 0xb6e73fff libEGL.so ???
0xb6e77000 - 0xb6f52fff libandroid_runtime.so ???
0xb6f53000 - 0xb6f56fff libstdc++.so ???
0xb6f57000 - 0xb6f6ffff libm.so ???
0xb6f71000 - 0xb6f77fff liblog.so ???
0xb6f79000 - 0xb6fd2fff libc.so ???
0xb6fdd000 - 0xb6fdffff libsigchain.so ???