Compare commits
223 Commits
master-lar
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
7fc25b8962 | ||
|
c65ed6573e | ||
|
a34c929f6f | ||
|
72e94c4ddb | ||
|
7933830cb7 | ||
|
240ed57ee1 | ||
|
8b7b28663f | ||
|
d269bd0f29 | ||
|
bad9e55ea5 | ||
|
6368037ef2 | ||
|
983d04d36e | ||
|
71a5ee37a5 | ||
|
79901bb99d | ||
|
f25a411200 | ||
|
faeb1f9b2b | ||
|
adca10c8ff | ||
|
e35167de75 | ||
|
9eb2c6fe6c | ||
|
67d5567177 | ||
|
a875991e73 | ||
|
a84d4fc426 | ||
|
3d225e288c | ||
|
1bbe2f29c9 | ||
|
638066b82e | ||
|
764c21f752 | ||
|
b5712766f6 | ||
|
4f417c8c0f | ||
|
fcb844ee32 | ||
|
17ad0c18b1 | ||
|
8762c82297 | ||
|
ea2e22b352 | ||
|
d48fa9d3a4 | ||
|
622bc036d6 | ||
|
b39ab626ab | ||
|
d986b9d311 | ||
|
2e266396ee | ||
|
fee47f4638 | ||
|
0203b0cbdd | ||
|
205b5ac6ed | ||
|
2f1b7adcd3 | ||
|
b0e5f26233 | ||
|
32901f6d4c | ||
|
46359276c8 | ||
|
6c8f80aa8b | ||
|
c1848484e1 | ||
|
6ce752d741 | ||
|
d9c532217e | ||
|
c77c51fae6 | ||
|
d091e5103f | ||
|
512cac3a1b | ||
|
85b27e4a69 | ||
|
ebba1800e4 | ||
|
139693446b | ||
|
11e17136db | ||
|
8915f7be39 | ||
|
4d69050717 | ||
|
f3d28e9c4a | ||
|
f97e47e55e | ||
|
25f913e981 | ||
|
7b25f70813 | ||
|
358c3b449c | ||
|
dee15c2547 | ||
|
e132514d80 | ||
|
d7c0bd0624 | ||
|
df280bb631 | ||
|
a8f79b0fde | ||
|
4912669df1 | ||
|
afa2539de4 | ||
|
c4c887c34a | ||
|
f4012f5cd9 | ||
|
76c51742c9 | ||
|
c199f5b122 | ||
|
815d51c343 | ||
|
442b45266d | ||
|
3f736ce086 | ||
|
bc44efdc27 | ||
|
b16c640e09 | ||
|
f820ead901 | ||
|
4b5dcd0e69 | ||
|
83523e066b | ||
|
e4cf26b851 | ||
|
92280b3c67 | ||
|
aa5ceea25b | ||
|
658eb44f3f | ||
|
8baa236daa | ||
|
48673cdb8c | ||
|
126a938fef | ||
|
081cbd64d7 | ||
|
ac69c577d8 | ||
|
4f512397f5 | ||
|
a1784ae81f | ||
|
2dda5fefdc | ||
|
68039850bc | ||
|
7b0d7a976e | ||
|
728bcdff61 | ||
|
98bea93a3e | ||
|
bcf4cc2f9a | ||
|
b1d3cdba8b | ||
|
8c49d62005 | ||
|
ee4d8ffed4 | ||
|
f9b60452e1 | ||
|
257123ca70 | ||
|
1be3027941 | ||
|
524508ff2f | ||
|
a22992081f | ||
|
dc16e41747 | ||
|
f217ae431f | ||
|
39e372dab6 | ||
|
fc62e72539 | ||
|
2d1b97a1ff | ||
|
ac2a3e466f | ||
|
ee69060bfd | ||
|
beee5c2e71 | ||
|
aa5ff205cb | ||
|
b458f36762 | ||
|
ef7575d35a | ||
|
a31f601d90 | ||
|
4ee6f3cd1c | ||
|
7685dfc567 | ||
|
dbf56c53a0 | ||
|
f948d8d623 | ||
|
01c8f7cf46 | ||
|
679d70f50b | ||
|
0d53bdd43d | ||
|
08a727d8f0 | ||
|
f74c85df88 | ||
|
0ff15b41ed | ||
|
4d06db5a1f | ||
|
3520fc314b | ||
|
8079ae192d | ||
|
d28bebcd16 | ||
|
1dcec01445 | ||
|
a057bc5d3e | ||
|
e8dbddf291 | ||
|
2d450f312b | ||
|
26ce7a2a89 | ||
|
3f4d090d70 | ||
|
f073540795 | ||
|
ee2d76fe90 | ||
|
8e8be001cb | ||
|
9178d8fa03 | ||
|
3bc3dad8f8 | ||
|
3365fe7986 | ||
|
dc5c38675c | ||
|
6ea9219d80 | ||
|
a3e9c02647 | ||
|
e3687f92c2 | ||
|
ab5ffb8b6c | ||
|
8794e39888 | ||
|
cde8616abf | ||
|
591ba326b3 | ||
|
ffa293221f | ||
|
c4e643dfb4 | ||
|
6a1a906773 | ||
|
47527e48e5 | ||
|
64c0d9c66d | ||
|
0dbae0cf3f | ||
|
4634d88f2e | ||
|
2997f45907 | ||
|
4959c18e98 | ||
|
0b7c158932 | ||
|
85e4cf8029 | ||
|
a840e1b710 | ||
|
0c426387b8 | ||
|
28c9c9b82c | ||
|
fed2e33bd1 | ||
|
e2eb4505d0 | ||
|
12213a5e15 | ||
|
440c1f79ef | ||
|
cd744acecc | ||
|
cca153368a | ||
|
ed3bf1c825 | ||
|
3c3c6680d3 | ||
|
11004944ad | ||
|
893e93a41f | ||
|
8785c0cb8f | ||
|
66295d1352 | ||
|
90cbb27528 | ||
|
f1ca06a079 | ||
|
69b745aa74 | ||
|
aa75fa5d4e | ||
|
0f27af628f | ||
|
9c6af3e29c | ||
|
50b2a7e647 | ||
|
751453c357 | ||
|
d88401cca9 | ||
|
18fc88ddc2 | ||
|
353e4cd585 | ||
|
cd6f90524a | ||
|
cfdf7cf8a9 | ||
|
48b9a40539 | ||
|
9b2d7192a4 | ||
|
ee25f6794b | ||
|
9208fbc224 | ||
|
bbd478ae73 | ||
|
eb08c16300 | ||
|
f2e6c177e4 | ||
|
14bbefbd96 | ||
|
b79454627e | ||
|
94f863af2c | ||
|
3b7262b0ee | ||
|
c63cf36a13 | ||
|
89947e7d86 | ||
|
854b9f74a0 | ||
|
9f00bce09a | ||
|
4c01a9c389 | ||
|
8aa26b79f9 | ||
|
924a8a2974 | ||
|
cef1bee150 | ||
|
cfaf27c37e | ||
|
7bebb27fb4 | ||
|
efa0310455 | ||
|
c332a1dcba | ||
|
30d41ec243 | ||
|
ba16fd3ffc | ||
|
d10c8c18ae | ||
|
bbbe29de11 | ||
|
10baadae40 | ||
|
0b6cc95246 | ||
|
63919583ba | ||
|
57e5b074f6 | ||
|
be21ad8190 | ||
|
6354cffeb0 |
26
.travis.yml
Normal file
26
.travis.yml
Normal file
@ -0,0 +1,26 @@
|
||||
# Travis build integration.
|
||||
# https://docs.travis-ci.com/
|
||||
language: cpp
|
||||
# TODO: add a clang build as well.
|
||||
compiler:
|
||||
- gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-4.8
|
||||
- g++-4.8
|
||||
# Travis sets CC/CXX to the system toolchain based on the `compiler`
|
||||
# selection. If clang is added, this should move to be set inside the
|
||||
# matrix.
|
||||
env:
|
||||
- USE_CC=gcc-4.8 USE_CXX=g++-4.8
|
||||
before_install: ./scripts/travis-checkout.sh
|
||||
script: ./scripts/travis-build.sh
|
||||
# TODO: add mac support
|
||||
os:
|
||||
- linux
|
||||
notifications:
|
||||
email:
|
||||
- google-breakpad-dev@googlegroups.com
|
294
Makefile.am
294
Makefile.am
@ -116,6 +116,7 @@ pkgconfig_DATA =
|
||||
if SYSTEM_TEST_LIBS
|
||||
TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
|
||||
TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
|
||||
TEST_DEPS =
|
||||
else
|
||||
TEST_CFLAGS = \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
@ -123,6 +124,7 @@ TEST_CFLAGS = \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
TEST_LIBS = src/testing/libtesting.a
|
||||
TEST_DEPS = $(TEST_LIBS)
|
||||
endif
|
||||
|
||||
## Libraries
|
||||
@ -138,6 +140,7 @@ check_LIBRARIES += src/testing/libtesting.a
|
||||
|
||||
if !SYSTEM_TEST_LIBS
|
||||
src_testing_libtesting_a_SOURCES = \
|
||||
src/breakpad_googletest_includes.h \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
@ -161,21 +164,33 @@ src_client_linux_libbreakpad_client_a_SOURCES = \
|
||||
src/client/linux/dump_writer_common/thread_info.cc \
|
||||
src/client/linux/dump_writer_common/ucontext_reader.cc \
|
||||
src/client/linux/handler/exception_handler.cc \
|
||||
src/client/linux/handler/exception_handler.h \
|
||||
src/client/linux/handler/minidump_descriptor.cc \
|
||||
src/client/linux/handler/minidump_descriptor.h \
|
||||
src/client/linux/log/log.cc \
|
||||
src/client/linux/log/log.h \
|
||||
src/client/linux/microdump_writer/microdump_writer.cc \
|
||||
src/client/linux/microdump_writer/microdump_writer.h \
|
||||
src/client/linux/minidump_writer/linux_core_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
|
||||
src/client/linux/minidump_writer/minidump_writer.cc \
|
||||
src/client/minidump_file_writer-inl.h \
|
||||
src/client/minidump_file_writer.cc \
|
||||
src/client/minidump_file_writer.h \
|
||||
src/common/convert_UTF.c \
|
||||
src/common/convert_UTF.h \
|
||||
src/common/md5.cc \
|
||||
src/common/md5.h \
|
||||
src/common/string_conversion.cc \
|
||||
src/common/string_conversion.h \
|
||||
src/common/linux/elf_core_dump.cc \
|
||||
src/common/linux/elfutils.cc \
|
||||
src/common/linux/elfutils.h \
|
||||
src/common/linux/file_id.cc \
|
||||
src/common/linux/file_id.h \
|
||||
src/common/linux/guid_creator.cc \
|
||||
src/common/linux/guid_creator.h \
|
||||
src/common/linux/linux_libc_support.cc \
|
||||
src/common/linux/memory_mapped_file.cc \
|
||||
src/common/linux/safe_readlink.cc
|
||||
@ -380,6 +395,7 @@ check_PROGRAMS += \
|
||||
src/processor/pathname_stripper_unittest \
|
||||
src/processor/postfix_evaluator_unittest \
|
||||
src/processor/proc_maps_linux_unittest \
|
||||
src/processor/range_map_shrink_down_unittest \
|
||||
src/processor/range_map_unittest \
|
||||
src/processor/stackwalker_amd64_unittest \
|
||||
src/processor/stackwalker_arm_unittest \
|
||||
@ -467,9 +483,12 @@ src_client_linux_linux_client_unittest_shlib_SOURCES = \
|
||||
src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
|
||||
src/common/linux/elf_core_dump.cc \
|
||||
src/common/linux/linux_libc_support_unittest.cc \
|
||||
src/common/linux/tests/auto_testfile.h \
|
||||
src/common/linux/tests/crash_generator.cc \
|
||||
src/common/memory_unittest.cc \
|
||||
src/common/tests/auto_tempdir.h \
|
||||
src/common/tests/file_utils.cc \
|
||||
src/common/tests/file_utils.h \
|
||||
src/processor/basic_code_modules.cc \
|
||||
src/processor/dump_context.cc \
|
||||
src/processor/dump_object.cc \
|
||||
@ -524,11 +543,14 @@ endif
|
||||
src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
|
||||
src/client/linux/linux_dumper_unittest_helper \
|
||||
src/client/linux/libbreakpad_client.a \
|
||||
$(TEST_DEPS) \
|
||||
src/libbreakpad.a
|
||||
|
||||
src_client_linux_linux_client_unittest_SOURCES =
|
||||
# The extra-long build id is for a test in minidump_writer_unittest.cc.
|
||||
src_client_linux_linux_client_unittest_LDFLAGS = \
|
||||
-Wl,-rpath,'$$ORIGIN'
|
||||
-Wl,-rpath,'$$ORIGIN' \
|
||||
-Wl,--build-id=0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
if ANDROID_HOST
|
||||
src_client_linux_linux_client_unittest_LDFLAGS += \
|
||||
-llog
|
||||
@ -559,9 +581,12 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/elf_reader.cc \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols.h \
|
||||
src/common/linux/elf_symbols_to_module.cc \
|
||||
src/common/linux/elf_symbols_to_module.h \
|
||||
src/common/linux/elfutils.cc \
|
||||
src/common/linux/file_id.cc \
|
||||
src/common/linux/linux_libc_support.cc \
|
||||
@ -571,7 +596,8 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
|
||||
|
||||
src_tools_linux_md2core_minidump_2_core_SOURCES = \
|
||||
src/common/linux/memory_mapped_file.cc \
|
||||
src/tools/linux/md2core/minidump-2-core.cc
|
||||
src/tools/linux/md2core/minidump-2-core.cc \
|
||||
src/tools/linux/md2core/minidump_memory_range.h
|
||||
|
||||
src_tools_linux_symupload_minidump_upload_SOURCES = \
|
||||
src/common/linux/http_upload.cc \
|
||||
@ -580,6 +606,9 @@ src_tools_linux_symupload_minidump_upload_LDADD = -ldl
|
||||
|
||||
src_tools_linux_symupload_sym_upload_SOURCES = \
|
||||
src/common/linux/http_upload.cc \
|
||||
src/common/linux/http_upload.h \
|
||||
src/common/linux/symbol_upload.cc \
|
||||
src/common/linux/symbol_upload.h \
|
||||
src/tools/linux/symupload/sym_upload.cc
|
||||
src_tools_linux_symupload_sym_upload_LDADD = -ldl
|
||||
|
||||
@ -595,13 +624,20 @@ src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/elf_reader.cc \
|
||||
src/common/mac/arch_utilities.cc \
|
||||
src/common/mac/dump_syms.cc \
|
||||
src/common/mac/dump_syms.h \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/file_id.h \
|
||||
src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_id.h \
|
||||
src/common/mac/macho_reader.cc \
|
||||
src/common/mac/macho_reader.h \
|
||||
src/common/mac/macho_utilities.cc \
|
||||
src/common/mac/macho_utilities.h \
|
||||
src/common/mac/macho_walker.cc \
|
||||
src/common/mac/macho_walker.h \
|
||||
src/tools/mac/dump_syms/dump_syms_tool.cc
|
||||
src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS= \
|
||||
-I$(top_srcdir)/src/third_party/mac_headers \
|
||||
@ -625,13 +661,20 @@ src_common_dumper_unittest_SOURCES = \
|
||||
src/common/stabs_to_module_unittest.cc \
|
||||
src/common/test_assembler.cc \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/bytereader.h \
|
||||
src/common/dwarf/bytereader-inl.h \
|
||||
src/common/dwarf/bytereader_unittest.cc \
|
||||
src/common/dwarf/cfi_assembler.cc \
|
||||
src/common/dwarf/cfi_assembler.h \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2diehandler_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/dwarf2reader.h \
|
||||
src/common/dwarf/elf_reader.cc \
|
||||
src/common/dwarf/elf_reader.h \
|
||||
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader_die_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader_test_common.h \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols_unittest.cc \
|
||||
@ -650,6 +693,8 @@ src_common_dumper_unittest_SOURCES = \
|
||||
src/common/linux/synth_elf.cc \
|
||||
src/common/linux/synth_elf_unittest.cc \
|
||||
src/common/linux/tests/crash_generator.cc \
|
||||
src/common/linux/tests/crash_generator.h \
|
||||
src/common/testdata/func-line-pairing.h \
|
||||
src/common/tests/file_utils.cc
|
||||
src_common_dumper_unittest_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) $(TEST_CFLAGS) \
|
||||
@ -672,6 +717,7 @@ src_common_mac_macho_reader_unittest_SOURCES = \
|
||||
src/common/dwarf/cfi_assembler.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/elf_reader.cc \
|
||||
src/common/mac/arch_utilities.cc \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/macho_id.cc \
|
||||
@ -971,6 +1017,16 @@ src_processor_postfix_evaluator_unittest_LDADD = \
|
||||
src/processor/pathname_stripper.o \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_processor_range_map_shrink_down_unittest_SOURCES = \
|
||||
src/processor/range_map_shrink_down_unittest.cc
|
||||
src_processor_range_map_shrink_down_unittest_LDADD = \
|
||||
src/processor/logging.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
$(TEST_LIBS) \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
src_processor_range_map_shrink_down_unittest_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) $(TEST_CFLAGS)
|
||||
|
||||
src_processor_range_map_unittest_SOURCES = \
|
||||
src/processor/range_map_unittest.cc
|
||||
src_processor_range_map_unittest_LDADD = \
|
||||
@ -1195,33 +1251,32 @@ endif !DISABLE_PROCESSOR
|
||||
## sed -e s/'^\(.*\)$'/'\t\1 \\'/
|
||||
EXTRA_DIST = \
|
||||
$(SCRIPTS) \
|
||||
src/processor/stackwalk_selftest_sol.s \
|
||||
src/client/linux/handler/Makefile \
|
||||
src/client/linux/handler/exception_handler.cc \
|
||||
src/client/linux/handler/exception_handler.h \
|
||||
src/client/linux/handler/minidump_descriptor.cc \
|
||||
src/client/linux/handler/minidump_descriptor.h \
|
||||
src/client/linux/handler/exception_handler_test.cc \
|
||||
src/client/linux/handler/linux_thread.cc \
|
||||
src/client/linux/handler/linux_thread.h \
|
||||
src/client/linux/handler/linux_thread_test.cc \
|
||||
src/client/linux/handler/minidump_generator.cc \
|
||||
src/client/linux/handler/minidump_generator.h \
|
||||
src/client/linux/handler/minidump_test.cc \
|
||||
src/client/linux/data/linux-gate-amd.sym \
|
||||
src/client/linux/data/linux-gate-intel.sym \
|
||||
src/client/mac/handler/breakpad_nlist_64.cc \
|
||||
src/client/mac/handler/breakpad_nlist_64.h \
|
||||
src/client/mac/handler/dynamic_images.cc \
|
||||
src/client/mac/handler/dynamic_images.h \
|
||||
src/client/mac/handler/exception_handler.cc \
|
||||
src/client/mac/handler/exception_handler.h \
|
||||
src/client/mac/handler/exception_handler_test.cc \
|
||||
src/client/mac/handler/mach_vm_compat.h \
|
||||
src/client/mac/handler/minidump_generator.cc \
|
||||
src/client/mac/handler/minidump_generator.h \
|
||||
src/client/mac/handler/minidump_generator_test.cc \
|
||||
src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
|
||||
src/client/mac/handler/minidump_tests32-Info.plist \
|
||||
src/client/mac/handler/minidump_tests64-Info.plist \
|
||||
src/client/mac/handler/obj-cTestCases-Info.plist \
|
||||
src/client/mac/handler/protected_memory_allocator.cc \
|
||||
src/client/mac/handler/protected_memory_allocator.h \
|
||||
src/client/minidump_file_writer-inl.h \
|
||||
src/client/minidump_file_writer.cc \
|
||||
src/client/minidump_file_writer.h \
|
||||
src/client/mac/handler/ucontext_compat.h \
|
||||
src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym \
|
||||
src/client/mac/tests/BreakpadFramework_Test.mm \
|
||||
src/client/mac/tests/crash_generation_server_test.cc \
|
||||
src/client/mac/tests/exception_handler_test.cc \
|
||||
src/client/mac/tests/minidump_generator_test.cc \
|
||||
src/client/mac/tests/minidump_generator_test_helper.cc \
|
||||
src/client/mac/tests/spawn_child_process.h \
|
||||
src/client/mac/tests/testlogging.h \
|
||||
src/client/minidump_file_writer_unittest.cc \
|
||||
src/client/solaris/handler/Makefile \
|
||||
src/client/solaris/handler/exception_handler.cc \
|
||||
@ -1232,44 +1287,24 @@ EXTRA_DIST = \
|
||||
src/client/solaris/handler/minidump_test.cc \
|
||||
src/client/solaris/handler/solaris_lwp.cc \
|
||||
src/client/solaris/handler/solaris_lwp.h \
|
||||
src/client/windows/breakpad_client.sln \
|
||||
src/client/windows/breakpad_client.gyp \
|
||||
src/client/windows/handler/exception_handler.cc \
|
||||
src/client/windows/handler/exception_handler.h \
|
||||
src/client/windows/handler/exception_handler.vcproj \
|
||||
src/client/windows/handler/exception_handler.gyp \
|
||||
src/client/windows/sender/crash_report_sender.cc \
|
||||
src/client/windows/sender/crash_report_sender.h \
|
||||
src/client/windows/sender/crash_report_sender.vcproj \
|
||||
src/common/convert_UTF.c \
|
||||
src/common/convert_UTF.h \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols.h \
|
||||
src/common/linux/elf_symbols_to_module.cc \
|
||||
src/common/linux/elf_symbols_to_module.h \
|
||||
src/common/linux/elfutils.cc \
|
||||
src/common/linux/elfutils.h \
|
||||
src/common/linux/file_id.cc \
|
||||
src/common/linux/file_id.h \
|
||||
src/common/linux/guid_creator.cc \
|
||||
src/common/linux/guid_creator.h \
|
||||
src/common/linux/http_upload.cc \
|
||||
src/common/linux/http_upload.h \
|
||||
src/client/windows/sender/crash_report_sender.gyp \
|
||||
src/common/dwarf/dwarf2diehandler.h \
|
||||
src/common/dwarf/dwarf2enums.h \
|
||||
src/common/dwarf/line_state_machine.h \
|
||||
src/common/dwarf/types.h \
|
||||
src/common/mac/arch_utilities.h \
|
||||
src/common/mac/byteswap.h \
|
||||
src/common/mac/HTTPMultipartUpload.h \
|
||||
src/common/mac/HTTPMultipartUpload.m \
|
||||
src/common/mac/dump_syms.h \
|
||||
src/common/mac/dump_syms.cc \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/file_id.h \
|
||||
src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_id.h \
|
||||
src/common/mac/macho_utilities.cc \
|
||||
src/common/mac/macho_utilities.h \
|
||||
src/common/mac/macho_walker.cc \
|
||||
src/common/mac/macho_walker.h \
|
||||
src/common/mac/string_utilities.cc \
|
||||
src/common/mac/string_utilities.h \
|
||||
src/common/md5.cc \
|
||||
src/common/md5.h \
|
||||
src/common/mac/super_fat_arch.h \
|
||||
src/common/scoped_ptr.h \
|
||||
src/common/solaris/dump_symbols.cc \
|
||||
src/common/solaris/dump_symbols.h \
|
||||
@ -1278,8 +1313,6 @@ EXTRA_DIST = \
|
||||
src/common/solaris/guid_creator.cc \
|
||||
src/common/solaris/guid_creator.h \
|
||||
src/common/solaris/message_output.h \
|
||||
src/common/string_conversion.cc \
|
||||
src/common/string_conversion.h \
|
||||
src/common/windows/guid_string.cc \
|
||||
src/common/windows/guid_string.h \
|
||||
src/common/windows/http_upload.cc \
|
||||
@ -1288,22 +1321,158 @@ EXTRA_DIST = \
|
||||
src/common/windows/pdb_source_line_writer.h \
|
||||
src/common/windows/string_utils-inl.h \
|
||||
src/common/windows/string_utils.cc \
|
||||
src/processor/stackwalk_common.cc \
|
||||
src/processor/stackwalk_common.h \
|
||||
src/processor/stackwalker_selftest_sol.s \
|
||||
src/processor/testdata/ascii_read_av_block_write.dmp \
|
||||
src/processor/testdata/ascii_read_av_clobber_write.dmp \
|
||||
src/processor/testdata/ascii_read_av_conditional.dmp \
|
||||
src/processor/testdata/ascii_read_av.dmp \
|
||||
src/processor/testdata/ascii_read_av_then_jmp.dmp \
|
||||
src/processor/testdata/ascii_read_av_xchg_write.dmp \
|
||||
src/processor/testdata/ascii_write_av_arg_to_call.dmp \
|
||||
src/processor/testdata/ascii_write_av.dmp \
|
||||
src/processor/testdata/exec_av_on_stack.dmp \
|
||||
src/processor/testdata/linux_divide_by_zero.dmp \
|
||||
src/processor/testdata/linux_executable_heap.dmp \
|
||||
src/processor/testdata/linux_executable_stack.dmp \
|
||||
src/processor/testdata/linux_inside_module_exe_region1.dmp \
|
||||
src/processor/testdata/linux_inside_module_exe_region2.dmp \
|
||||
src/processor/testdata/linux_jmp_to_0.dmp \
|
||||
src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
|
||||
src/processor/testdata/linux_null_dereference.dmp \
|
||||
src/processor/testdata/linux_null_read_av.dmp \
|
||||
src/processor/testdata/linux_outside_module.dmp \
|
||||
src/processor/testdata/linux_overflow.dmp \
|
||||
src/processor/testdata/linux_raise_sigabrt.dmp \
|
||||
src/processor/testdata/linux_stack_pointer_in_module.dmp \
|
||||
src/processor/testdata/linux_stack_pointer_in_stack.dmp \
|
||||
src/processor/testdata/linux_stacksmash.dmp \
|
||||
src/processor/testdata/linux_write_to_nonwritable_module.dmp \
|
||||
src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
|
||||
src/processor/testdata/linux_write_to_outside_module.dmp \
|
||||
src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
|
||||
src/processor/testdata/linux_write_to_under_4k.dmp \
|
||||
src/processor/testdata/microdump-arm64.dmp \
|
||||
src/processor/testdata/microdump-arm.dmp \
|
||||
src/processor/testdata/microdump-mips32.dmp \
|
||||
src/processor/testdata/microdump-mips64.dmp \
|
||||
src/processor/testdata/microdump-multiple.dmp \
|
||||
src/processor/testdata/microdump.stackwalk-arm64.out \
|
||||
src/processor/testdata/microdump.stackwalk-arm.out \
|
||||
src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
|
||||
src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
|
||||
src/processor/testdata/microdump-x86.dmp \
|
||||
src/processor/testdata/minidump2.dmp \
|
||||
src/processor/testdata/minidump2.dump.out \
|
||||
src/processor/testdata/minidump2.stackwalk.machine_readable.out \
|
||||
src/processor/testdata/minidump2.stackwalk.out \
|
||||
src/processor/testdata/module0.out \
|
||||
src/processor/testdata/module1.out \
|
||||
src/processor/testdata/module2.out \
|
||||
src/processor/testdata/module3_bad.out \
|
||||
src/processor/testdata/module4_bad.out \
|
||||
src/processor/testdata/null_read_av.dmp \
|
||||
src/processor/testdata/null_write_av.dmp \
|
||||
src/processor/testdata/read_av_clobber_write.dmp \
|
||||
src/processor/testdata/read_av_conditional.dmp \
|
||||
src/processor/testdata/read_av_non_null.dmp \
|
||||
src/processor/testdata/stack_exhaustion.dmp \
|
||||
src/processor/testdata/write_av_non_null.dmp \
|
||||
src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
|
||||
src/processor/testdata/symbols/ld-2.13.so/C32AD7E235EA6112E02A5B9D6219C4850/ld-2.13.so.sym \
|
||||
src/processor/testdata/symbols/libc-2.13.so/F4F8DFCD5A5FB5A7CE64717E9E6AE3890/libc-2.13.so.sym \
|
||||
src/processor/testdata/symbols/libgcc_s.so.1/18B180F90887D8F8B5C35D185444AF4C0/libgcc_s.so.1.sym \
|
||||
src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
|
||||
src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
|
||||
src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
|
||||
src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
|
||||
src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
|
||||
src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
|
||||
src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
|
||||
src/processor/testdata/test_app.cc \
|
||||
src/tools/linux/dump_syms/Makefile \
|
||||
src/tools/linux/dump_syms/dump_syms.cc \
|
||||
src/tools/linux/symupload/Makefile \
|
||||
src/tools/linux/symupload/minidump_upload.cc \
|
||||
src/tools/linux/symupload/sym_upload.cc \
|
||||
src/testing/gtest/include/gtest/gtest.h \
|
||||
src/testing/gtest/include/gtest/gtest-death-test.h \
|
||||
src/testing/gtest/include/gtest/gtest-message.h \
|
||||
src/testing/gtest/include/gtest/gtest-param-test.h \
|
||||
src/testing/gtest/include/gtest/gtest-printers.h \
|
||||
src/testing/gtest/include/gtest/gtest-spi.h \
|
||||
src/testing/gtest/include/gtest/gtest-test-part.h \
|
||||
src/testing/gtest/include/gtest/gtest-typed-test.h \
|
||||
src/testing/gtest/include/gtest/gtest_pred_impl.h \
|
||||
src/testing/gtest/include/gtest/gtest_prod.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-filepath.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-internal.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-param-util.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-port.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-string.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-tuple.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-type-util.h \
|
||||
src/testing/gtest/src/gtest.cc \
|
||||
src/testing/gtest/src/gtest-death-test.cc \
|
||||
src/testing/gtest/src/gtest-filepath.cc \
|
||||
src/testing/gtest/src/gtest-internal-inl.h \
|
||||
src/testing/gtest/src/gtest-port.cc \
|
||||
src/testing/gtest/src/gtest-printers.cc \
|
||||
src/testing/gtest/src/gtest-test-part.cc \
|
||||
src/testing/gtest/src/gtest-typed-test.cc \
|
||||
src/testing/include/gmock/gmock.h \
|
||||
src/testing/include/gmock/gmock-actions.h \
|
||||
src/testing/include/gmock/gmock-cardinalities.h \
|
||||
src/testing/include/gmock/gmock-generated-actions.h \
|
||||
src/testing/include/gmock/gmock-generated-function-mockers.h \
|
||||
src/testing/include/gmock/gmock-generated-matchers.h \
|
||||
src/testing/include/gmock/gmock-generated-nice-strict.h \
|
||||
src/testing/include/gmock/gmock-matchers.h \
|
||||
src/testing/include/gmock/gmock-more-actions.h \
|
||||
src/testing/include/gmock/gmock-more-matchers.h \
|
||||
src/testing/include/gmock/gmock-spec-builders.h \
|
||||
src/testing/include/gmock/internal/gmock-generated-internal-utils.h \
|
||||
src/testing/include/gmock/internal/gmock-internal-utils.h \
|
||||
src/testing/include/gmock/internal/gmock-port.h \
|
||||
src/testing/src/gmock.cc \
|
||||
src/testing/src/gmock-cardinalities.cc \
|
||||
src/testing/src/gmock-internal-utils.cc \
|
||||
src/testing/src/gmock-matchers.cc \
|
||||
src/testing/src/gmock-spec-builders.cc \
|
||||
src/testing/src/gmock_main.cc \
|
||||
src/third_party/curl/COPYING \
|
||||
src/third_party/curl/curlbuild.h \
|
||||
src/third_party/curl/curl.h \
|
||||
src/third_party/curl/curlrules.h \
|
||||
src/third_party/curl/curlver.h \
|
||||
src/third_party/curl/easy.h \
|
||||
src/third_party/curl/mprintf.h \
|
||||
src/third_party/curl/multi.h \
|
||||
src/third_party/curl/stdcheaders.h \
|
||||
src/third_party/curl/typecheck-gcc.h \
|
||||
src/third_party/curl/types.h \
|
||||
src/third_party/mac_headers/architecture/byte_order.h \
|
||||
src/third_party/mac_headers/i386/_types.h \
|
||||
src/third_party/mac_headers/mach/boolean.h \
|
||||
src/third_party/mac_headers/mach/i386/boolean.h \
|
||||
src/third_party/mac_headers/mach/i386/vm_param.h \
|
||||
src/third_party/mac_headers/mach/i386/vm_types.h \
|
||||
src/third_party/mac_headers/mach/machine/boolean.h \
|
||||
src/third_party/mac_headers/mach/machine.h \
|
||||
src/third_party/mac_headers/mach/machine/thread_state.h \
|
||||
src/third_party/mac_headers/mach/machine/thread_status.h \
|
||||
src/third_party/mac_headers/mach/machine/vm_types.h \
|
||||
src/third_party/mac_headers/mach-o/arch.h \
|
||||
src/third_party/mac_headers/mach-o/fat.h \
|
||||
src/third_party/mac_headers/mach-o/loader.h \
|
||||
src/third_party/mac_headers/mach-o/nlist.h \
|
||||
src/third_party/mac_headers/mach/thread_status.h \
|
||||
src/third_party/mac_headers/mach/vm_prot.h \
|
||||
src/third_party/mac_headers/README \
|
||||
src/third_party/musl/README \
|
||||
src/third_party/musl/COPYRIGHT \
|
||||
src/third_party/musl/README.breakpad \
|
||||
src/third_party/musl/VERSION \
|
||||
src/third_party/musl/include/elf.h \
|
||||
src/tools/mac/crash_report/crash_report.mm \
|
||||
src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
|
||||
src/tools/mac/crash_report/on_demand_symbol_supplier.h \
|
||||
@ -1322,15 +1491,20 @@ EXTRA_DIST = \
|
||||
src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.cc \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.h \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.vcproj \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.gyp \
|
||||
src/tools/windows/dump_syms/dump_syms.cc \
|
||||
src/tools/windows/dump_syms/dump_syms.vcproj \
|
||||
src/tools/windows/dump_syms/dump_syms.gyp \
|
||||
src/tools/windows/dump_syms/run_regtest.sh \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest64.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_reorder_bbs.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_reorder_funcs.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_stretched.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_stretched_filled.sym \
|
||||
src/tools/windows/symupload/symupload.cc \
|
||||
src/tools/windows/symupload/symupload.vcproj
|
||||
src/tools/windows/symupload/symupload.gyp
|
||||
|
||||
mostlyclean-local:
|
||||
-find src -name '*.dwo' -exec rm -f {} +
|
||||
|
462
Makefile.in
462
Makefile.in
@ -194,6 +194,7 @@ EXTRA_PROGRAMS = $(am__EXEEXT_1)
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest \
|
||||
@ -298,17 +299,25 @@ am__src_client_linux_libbreakpad_client_a_SOURCES_DIST = \
|
||||
src/client/linux/dump_writer_common/thread_info.cc \
|
||||
src/client/linux/dump_writer_common/ucontext_reader.cc \
|
||||
src/client/linux/handler/exception_handler.cc \
|
||||
src/client/linux/handler/exception_handler.h \
|
||||
src/client/linux/handler/minidump_descriptor.cc \
|
||||
src/client/linux/log/log.cc \
|
||||
src/client/linux/handler/minidump_descriptor.h \
|
||||
src/client/linux/log/log.cc src/client/linux/log/log.h \
|
||||
src/client/linux/microdump_writer/microdump_writer.cc \
|
||||
src/client/linux/microdump_writer/microdump_writer.h \
|
||||
src/client/linux/minidump_writer/linux_core_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
|
||||
src/client/linux/minidump_writer/minidump_writer.cc \
|
||||
src/client/minidump_file_writer.cc src/common/convert_UTF.c \
|
||||
src/common/md5.cc src/common/string_conversion.cc \
|
||||
src/client/minidump_file_writer-inl.h \
|
||||
src/client/minidump_file_writer.cc \
|
||||
src/client/minidump_file_writer.h src/common/convert_UTF.c \
|
||||
src/common/convert_UTF.h src/common/md5.cc src/common/md5.h \
|
||||
src/common/string_conversion.cc src/common/string_conversion.h \
|
||||
src/common/linux/elf_core_dump.cc src/common/linux/elfutils.cc \
|
||||
src/common/linux/file_id.cc src/common/linux/guid_creator.cc \
|
||||
src/common/linux/elfutils.h src/common/linux/file_id.cc \
|
||||
src/common/linux/file_id.h src/common/linux/guid_creator.cc \
|
||||
src/common/linux/guid_creator.h \
|
||||
src/common/linux/linux_libc_support.cc \
|
||||
src/common/linux/memory_mapped_file.cc \
|
||||
src/common/linux/safe_readlink.cc \
|
||||
@ -488,6 +497,7 @@ src_libbreakpad_a_OBJECTS = $(am_src_libbreakpad_a_OBJECTS)
|
||||
src_testing_libtesting_a_AR = $(AR) $(ARFLAGS)
|
||||
src_testing_libtesting_a_LIBADD =
|
||||
am__src_testing_libtesting_a_SOURCES_DIST = \
|
||||
src/breakpad_googletest_includes.h \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
@ -571,6 +581,7 @@ src_third_party_libdisasm_libdisasm_a_OBJECTS = \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest$(EXEEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest$(EXEEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest$(EXEEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest$(EXEEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest$(EXEEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest$(EXEEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest$(EXEEXT) \
|
||||
@ -597,6 +608,7 @@ src_client_linux_linux_client_unittest_LINK = $(CCLD) $(AM_CFLAGS) \
|
||||
$(CFLAGS) $(src_client_linux_linux_client_unittest_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
|
||||
src/breakpad_googletest_includes.h \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc \
|
||||
@ -612,8 +624,10 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
|
||||
src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
|
||||
src/common/linux/elf_core_dump.cc \
|
||||
src/common/linux/linux_libc_support_unittest.cc \
|
||||
src/common/linux/tests/auto_testfile.h \
|
||||
src/common/linux/tests/crash_generator.cc \
|
||||
src/common/memory_unittest.cc src/common/tests/file_utils.cc \
|
||||
src/common/memory_unittest.cc src/common/tests/auto_tempdir.h \
|
||||
src/common/tests/file_utils.cc src/common/tests/file_utils.h \
|
||||
src/processor/basic_code_modules.cc \
|
||||
src/processor/dump_context.cc src/processor/dump_object.cc \
|
||||
src/processor/logging.cc src/processor/minidump.cc \
|
||||
@ -684,13 +698,19 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
|
||||
src/common/stabs_to_module.cc \
|
||||
src/common/stabs_to_module_unittest.cc \
|
||||
src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/bytereader.h \
|
||||
src/common/dwarf/bytereader-inl.h \
|
||||
src/common/dwarf/bytereader_unittest.cc \
|
||||
src/common/dwarf/cfi_assembler.cc \
|
||||
src/common/dwarf/cfi_assembler.h \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2diehandler_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/dwarf2reader.h src/common/dwarf/elf_reader.cc \
|
||||
src/common/dwarf/elf_reader.h \
|
||||
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader_die_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader_test_common.h \
|
||||
src/common/linux/crc32.cc src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols_unittest.cc \
|
||||
src/common/linux/elf_core_dump.cc \
|
||||
@ -707,6 +727,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
|
||||
src/common/linux/synth_elf.cc \
|
||||
src/common/linux/synth_elf_unittest.cc \
|
||||
src/common/linux/tests/crash_generator.cc \
|
||||
src/common/linux/tests/crash_generator.h \
|
||||
src/common/testdata/func-line-pairing.h \
|
||||
src/common/tests/file_utils.cc
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_common_dumper_unittest_OBJECTS = src/common/src_common_dumper_unittest-byte_cursor_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cfi_to_module.$(OBJEXT) \
|
||||
@ -730,6 +752,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT) \
|
||||
@ -767,6 +790,7 @@ am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
|
||||
src/common/dwarf/cfi_assembler.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/elf_reader.cc \
|
||||
src/common/mac/arch_utilities.cc src/common/mac/file_id.cc \
|
||||
src/common/mac/macho_id.cc src/common/mac/macho_reader.cc \
|
||||
src/common/mac/macho_reader_unittest.cc \
|
||||
@ -785,6 +809,7 @@ am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-file_id.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_id.$(OBJEXT) \
|
||||
@ -1147,6 +1172,17 @@ src_processor_proc_maps_linux_unittest_OBJECTS = \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
|
||||
am__src_processor_range_map_shrink_down_unittest_SOURCES_DIST = \
|
||||
src/processor/range_map_shrink_down_unittest.cc
|
||||
@DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_shrink_down_unittest_OBJECTS = src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.$(OBJEXT)
|
||||
src_processor_range_map_shrink_down_unittest_OBJECTS = \
|
||||
$(am_src_processor_range_map_shrink_down_unittest_OBJECTS)
|
||||
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_DEPENDENCIES = \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
|
||||
am__src_processor_range_map_unittest_SOURCES_DIST = \
|
||||
src/processor/range_map_unittest.cc
|
||||
@DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_unittest_OBJECTS = src/processor/range_map_unittest.$(OBJEXT)
|
||||
@ -1343,9 +1379,12 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
|
||||
src/common/module.cc src/common/stabs_reader.cc \
|
||||
src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc src/common/linux/crc32.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/elf_reader.cc src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols.h \
|
||||
src/common/linux/elf_symbols_to_module.cc \
|
||||
src/common/linux/elf_symbols_to_module.h \
|
||||
src/common/linux/elfutils.cc src/common/linux/file_id.cc \
|
||||
src/common/linux/linux_libc_support.cc \
|
||||
src/common/linux/memory_mapped_file.cc \
|
||||
@ -1361,6 +1400,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \
|
||||
@ -1375,7 +1415,8 @@ src_tools_linux_dump_syms_dump_syms_OBJECTS = \
|
||||
src_tools_linux_dump_syms_dump_syms_LDADD = $(LDADD)
|
||||
am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST = \
|
||||
src/common/linux/memory_mapped_file.cc \
|
||||
src/tools/linux/md2core/minidump-2-core.cc
|
||||
src/tools/linux/md2core/minidump-2-core.cc \
|
||||
src/tools/linux/md2core/minidump_memory_range.h
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_OBJECTS = src/common/linux/memory_mapped_file.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.$(OBJEXT)
|
||||
src_tools_linux_md2core_minidump_2_core_OBJECTS = \
|
||||
@ -1397,9 +1438,12 @@ src_tools_linux_symupload_minidump_upload_OBJECTS = \
|
||||
$(am_src_tools_linux_symupload_minidump_upload_OBJECTS)
|
||||
src_tools_linux_symupload_minidump_upload_DEPENDENCIES =
|
||||
am__src_tools_linux_symupload_sym_upload_SOURCES_DIST = \
|
||||
src/common/linux/http_upload.cc \
|
||||
src/common/linux/http_upload.cc src/common/linux/http_upload.h \
|
||||
src/common/linux/symbol_upload.cc \
|
||||
src/common/linux/symbol_upload.h \
|
||||
src/tools/linux/symupload/sym_upload.cc
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_symupload_sym_upload_OBJECTS = src/common/linux/http_upload.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload.$(OBJEXT)
|
||||
src_tools_linux_symupload_sym_upload_OBJECTS = \
|
||||
$(am_src_tools_linux_symupload_sym_upload_OBJECTS)
|
||||
@ -1413,11 +1457,15 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/elf_reader.cc \
|
||||
src/common/mac/arch_utilities.cc src/common/mac/dump_syms.cc \
|
||||
src/common/mac/file_id.cc src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_reader.cc \
|
||||
src/common/mac/dump_syms.h src/common/mac/file_id.cc \
|
||||
src/common/mac/file_id.h src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_id.h src/common/mac/macho_reader.cc \
|
||||
src/common/mac/macho_reader.h \
|
||||
src/common/mac/macho_utilities.cc \
|
||||
src/common/mac/macho_walker.cc \
|
||||
src/common/mac/macho_utilities.h \
|
||||
src/common/mac/macho_walker.cc src/common/mac/macho_walker.h \
|
||||
src/tools/mac/dump_syms/dump_syms_tool.cc
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_mac_dump_syms_dump_syms_mac_OBJECTS = src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.$(OBJEXT) \
|
||||
@ -1430,6 +1478,7 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.$(OBJEXT) \
|
||||
@ -1523,6 +1572,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \
|
||||
$(src_processor_pathname_stripper_unittest_SOURCES) \
|
||||
$(src_processor_postfix_evaluator_unittest_SOURCES) \
|
||||
$(src_processor_proc_maps_linux_unittest_SOURCES) \
|
||||
$(src_processor_range_map_shrink_down_unittest_SOURCES) \
|
||||
$(src_processor_range_map_unittest_SOURCES) \
|
||||
$(src_processor_stackwalker_address_list_unittest_SOURCES) \
|
||||
$(src_processor_stackwalker_amd64_unittest_SOURCES) \
|
||||
@ -1572,6 +1622,7 @@ DIST_SOURCES = \
|
||||
$(am__src_processor_pathname_stripper_unittest_SOURCES_DIST) \
|
||||
$(am__src_processor_postfix_evaluator_unittest_SOURCES_DIST) \
|
||||
$(am__src_processor_proc_maps_linux_unittest_SOURCES_DIST) \
|
||||
$(am__src_processor_range_map_shrink_down_unittest_SOURCES_DIST) \
|
||||
$(am__src_processor_range_map_unittest_SOURCES_DIST) \
|
||||
$(am__src_processor_stackwalker_address_list_unittest_SOURCES_DIST) \
|
||||
$(am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST) \
|
||||
@ -2005,11 +2056,14 @@ pkgconfig_DATA = $(am__append_6) $(am__append_9)
|
||||
@SYSTEM_TEST_LIBS_TRUE@TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
|
||||
@SYSTEM_TEST_LIBS_FALSE@TEST_LIBS = src/testing/libtesting.a
|
||||
@SYSTEM_TEST_LIBS_TRUE@TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
|
||||
@SYSTEM_TEST_LIBS_FALSE@TEST_DEPS = $(TEST_LIBS)
|
||||
@SYSTEM_TEST_LIBS_TRUE@TEST_DEPS =
|
||||
check_LIBRARIES = src/testing/libtesting.a
|
||||
noinst_LIBRARIES = $(am__append_7)
|
||||
lib_LIBRARIES = $(am__append_5) $(am__append_8)
|
||||
CLEANFILES = $(am__append_13)
|
||||
@SYSTEM_TEST_LIBS_FALSE@src_testing_libtesting_a_SOURCES = \
|
||||
@SYSTEM_TEST_LIBS_FALSE@ src/breakpad_googletest_includes.h \
|
||||
@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/gtest-all.cc \
|
||||
@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/gtest_main.cc \
|
||||
@SYSTEM_TEST_LIBS_FALSE@ src/testing/src/gmock-all.cc
|
||||
@ -2022,20 +2076,32 @@ CLEANFILES = $(am__append_13)
|
||||
@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/thread_info.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/ucontext_reader.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.h \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.h \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/log/log.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/log/log.h \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.h \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_core_dumper.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_dumper.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/minidump_file_writer-inl.h \
|
||||
@LINUX_HOST_TRUE@ src/client/minidump_file_writer.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/convert_UTF.c src/common/md5.cc \
|
||||
@LINUX_HOST_TRUE@ src/client/minidump_file_writer.h \
|
||||
@LINUX_HOST_TRUE@ src/common/convert_UTF.c \
|
||||
@LINUX_HOST_TRUE@ src/common/convert_UTF.h src/common/md5.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/md5.h \
|
||||
@LINUX_HOST_TRUE@ src/common/string_conversion.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/string_conversion.h \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/elfutils.h \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/file_id.h \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/guid_creator.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/guid_creator.h \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.cc \
|
||||
@ -2223,9 +2289,12 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support_unittest.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/tests/auto_testfile.h \
|
||||
@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/memory_unittest.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/tests/auto_tempdir.h \
|
||||
@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc \
|
||||
@LINUX_HOST_TRUE@ src/common/tests/file_utils.h \
|
||||
@LINUX_HOST_TRUE@ src/processor/basic_code_modules.cc \
|
||||
@LINUX_HOST_TRUE@ src/processor/dump_context.cc \
|
||||
@LINUX_HOST_TRUE@ src/processor/dump_object.cc \
|
||||
@ -2269,11 +2338,15 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/linux_dumper_unittest_helper \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/libbreakpad_client.a \
|
||||
@LINUX_HOST_TRUE@ $(TEST_DEPS) \
|
||||
@LINUX_HOST_TRUE@ src/libbreakpad.a
|
||||
|
||||
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_SOURCES =
|
||||
# The extra-long build id is for a test in minidump_writer_unittest.cc.
|
||||
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDFLAGS = \
|
||||
@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' $(am__append_24)
|
||||
@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' \
|
||||
@LINUX_HOST_TRUE@ -Wl,--build-id=0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \
|
||||
@LINUX_HOST_TRUE@ $(am__append_24)
|
||||
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDADD = \
|
||||
@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib \
|
||||
@LINUX_HOST_TRUE@ $(TEST_LIBS)
|
||||
@ -2298,9 +2371,12 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
|
||||
@ -2310,7 +2386,8 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_SOURCES = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.cc
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_memory_range.h
|
||||
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_SOURCES = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.cc \
|
||||
@ -2319,6 +2396,9 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_LDADD = -ldl
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_SOURCES = \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload.cc
|
||||
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_LDADD = -ldl
|
||||
@ -2334,13 +2414,20 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/mac/dump_syms/dump_syms_tool.cc
|
||||
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS = \
|
||||
@ -2365,13 +2452,20 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/test_assembler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader-inl.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_test_common.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \
|
||||
@ -2390,6 +2484,8 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/testdata/func-line-pairing.h \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc
|
||||
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_CPPFLAGS = \
|
||||
@ -2414,6 +2510,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
|
||||
@ -2745,6 +2842,18 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_SOURCES = \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest.cc
|
||||
|
||||
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_LDADD = \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_CPPFLAGS = \
|
||||
@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
|
||||
|
||||
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_SOURCES = \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest.cc
|
||||
|
||||
@ -2982,33 +3091,32 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(SCRIPTS) \
|
||||
src/processor/stackwalk_selftest_sol.s \
|
||||
src/client/linux/handler/Makefile \
|
||||
src/client/linux/handler/exception_handler.cc \
|
||||
src/client/linux/handler/exception_handler.h \
|
||||
src/client/linux/handler/minidump_descriptor.cc \
|
||||
src/client/linux/handler/minidump_descriptor.h \
|
||||
src/client/linux/handler/exception_handler_test.cc \
|
||||
src/client/linux/handler/linux_thread.cc \
|
||||
src/client/linux/handler/linux_thread.h \
|
||||
src/client/linux/handler/linux_thread_test.cc \
|
||||
src/client/linux/handler/minidump_generator.cc \
|
||||
src/client/linux/handler/minidump_generator.h \
|
||||
src/client/linux/handler/minidump_test.cc \
|
||||
src/client/linux/data/linux-gate-amd.sym \
|
||||
src/client/linux/data/linux-gate-intel.sym \
|
||||
src/client/mac/handler/breakpad_nlist_64.cc \
|
||||
src/client/mac/handler/breakpad_nlist_64.h \
|
||||
src/client/mac/handler/dynamic_images.cc \
|
||||
src/client/mac/handler/dynamic_images.h \
|
||||
src/client/mac/handler/exception_handler.cc \
|
||||
src/client/mac/handler/exception_handler.h \
|
||||
src/client/mac/handler/exception_handler_test.cc \
|
||||
src/client/mac/handler/mach_vm_compat.h \
|
||||
src/client/mac/handler/minidump_generator.cc \
|
||||
src/client/mac/handler/minidump_generator.h \
|
||||
src/client/mac/handler/minidump_generator_test.cc \
|
||||
src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
|
||||
src/client/mac/handler/minidump_tests32-Info.plist \
|
||||
src/client/mac/handler/minidump_tests64-Info.plist \
|
||||
src/client/mac/handler/obj-cTestCases-Info.plist \
|
||||
src/client/mac/handler/protected_memory_allocator.cc \
|
||||
src/client/mac/handler/protected_memory_allocator.h \
|
||||
src/client/minidump_file_writer-inl.h \
|
||||
src/client/minidump_file_writer.cc \
|
||||
src/client/minidump_file_writer.h \
|
||||
src/client/mac/handler/ucontext_compat.h \
|
||||
src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym \
|
||||
src/client/mac/tests/BreakpadFramework_Test.mm \
|
||||
src/client/mac/tests/crash_generation_server_test.cc \
|
||||
src/client/mac/tests/exception_handler_test.cc \
|
||||
src/client/mac/tests/minidump_generator_test.cc \
|
||||
src/client/mac/tests/minidump_generator_test_helper.cc \
|
||||
src/client/mac/tests/spawn_child_process.h \
|
||||
src/client/mac/tests/testlogging.h \
|
||||
src/client/minidump_file_writer_unittest.cc \
|
||||
src/client/solaris/handler/Makefile \
|
||||
src/client/solaris/handler/exception_handler.cc \
|
||||
@ -3019,44 +3127,24 @@ EXTRA_DIST = \
|
||||
src/client/solaris/handler/minidump_test.cc \
|
||||
src/client/solaris/handler/solaris_lwp.cc \
|
||||
src/client/solaris/handler/solaris_lwp.h \
|
||||
src/client/windows/breakpad_client.sln \
|
||||
src/client/windows/breakpad_client.gyp \
|
||||
src/client/windows/handler/exception_handler.cc \
|
||||
src/client/windows/handler/exception_handler.h \
|
||||
src/client/windows/handler/exception_handler.vcproj \
|
||||
src/client/windows/handler/exception_handler.gyp \
|
||||
src/client/windows/sender/crash_report_sender.cc \
|
||||
src/client/windows/sender/crash_report_sender.h \
|
||||
src/client/windows/sender/crash_report_sender.vcproj \
|
||||
src/common/convert_UTF.c \
|
||||
src/common/convert_UTF.h \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols.h \
|
||||
src/common/linux/elf_symbols_to_module.cc \
|
||||
src/common/linux/elf_symbols_to_module.h \
|
||||
src/common/linux/elfutils.cc \
|
||||
src/common/linux/elfutils.h \
|
||||
src/common/linux/file_id.cc \
|
||||
src/common/linux/file_id.h \
|
||||
src/common/linux/guid_creator.cc \
|
||||
src/common/linux/guid_creator.h \
|
||||
src/common/linux/http_upload.cc \
|
||||
src/common/linux/http_upload.h \
|
||||
src/client/windows/sender/crash_report_sender.gyp \
|
||||
src/common/dwarf/dwarf2diehandler.h \
|
||||
src/common/dwarf/dwarf2enums.h \
|
||||
src/common/dwarf/line_state_machine.h \
|
||||
src/common/dwarf/types.h \
|
||||
src/common/mac/arch_utilities.h \
|
||||
src/common/mac/byteswap.h \
|
||||
src/common/mac/HTTPMultipartUpload.h \
|
||||
src/common/mac/HTTPMultipartUpload.m \
|
||||
src/common/mac/dump_syms.h \
|
||||
src/common/mac/dump_syms.cc \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/file_id.h \
|
||||
src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_id.h \
|
||||
src/common/mac/macho_utilities.cc \
|
||||
src/common/mac/macho_utilities.h \
|
||||
src/common/mac/macho_walker.cc \
|
||||
src/common/mac/macho_walker.h \
|
||||
src/common/mac/string_utilities.cc \
|
||||
src/common/mac/string_utilities.h \
|
||||
src/common/md5.cc \
|
||||
src/common/md5.h \
|
||||
src/common/mac/super_fat_arch.h \
|
||||
src/common/scoped_ptr.h \
|
||||
src/common/solaris/dump_symbols.cc \
|
||||
src/common/solaris/dump_symbols.h \
|
||||
@ -3065,8 +3153,6 @@ EXTRA_DIST = \
|
||||
src/common/solaris/guid_creator.cc \
|
||||
src/common/solaris/guid_creator.h \
|
||||
src/common/solaris/message_output.h \
|
||||
src/common/string_conversion.cc \
|
||||
src/common/string_conversion.h \
|
||||
src/common/windows/guid_string.cc \
|
||||
src/common/windows/guid_string.h \
|
||||
src/common/windows/http_upload.cc \
|
||||
@ -3075,22 +3161,158 @@ EXTRA_DIST = \
|
||||
src/common/windows/pdb_source_line_writer.h \
|
||||
src/common/windows/string_utils-inl.h \
|
||||
src/common/windows/string_utils.cc \
|
||||
src/processor/stackwalk_common.cc \
|
||||
src/processor/stackwalk_common.h \
|
||||
src/processor/stackwalker_selftest_sol.s \
|
||||
src/processor/testdata/ascii_read_av_block_write.dmp \
|
||||
src/processor/testdata/ascii_read_av_clobber_write.dmp \
|
||||
src/processor/testdata/ascii_read_av_conditional.dmp \
|
||||
src/processor/testdata/ascii_read_av.dmp \
|
||||
src/processor/testdata/ascii_read_av_then_jmp.dmp \
|
||||
src/processor/testdata/ascii_read_av_xchg_write.dmp \
|
||||
src/processor/testdata/ascii_write_av_arg_to_call.dmp \
|
||||
src/processor/testdata/ascii_write_av.dmp \
|
||||
src/processor/testdata/exec_av_on_stack.dmp \
|
||||
src/processor/testdata/linux_divide_by_zero.dmp \
|
||||
src/processor/testdata/linux_executable_heap.dmp \
|
||||
src/processor/testdata/linux_executable_stack.dmp \
|
||||
src/processor/testdata/linux_inside_module_exe_region1.dmp \
|
||||
src/processor/testdata/linux_inside_module_exe_region2.dmp \
|
||||
src/processor/testdata/linux_jmp_to_0.dmp \
|
||||
src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
|
||||
src/processor/testdata/linux_null_dereference.dmp \
|
||||
src/processor/testdata/linux_null_read_av.dmp \
|
||||
src/processor/testdata/linux_outside_module.dmp \
|
||||
src/processor/testdata/linux_overflow.dmp \
|
||||
src/processor/testdata/linux_raise_sigabrt.dmp \
|
||||
src/processor/testdata/linux_stack_pointer_in_module.dmp \
|
||||
src/processor/testdata/linux_stack_pointer_in_stack.dmp \
|
||||
src/processor/testdata/linux_stacksmash.dmp \
|
||||
src/processor/testdata/linux_write_to_nonwritable_module.dmp \
|
||||
src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
|
||||
src/processor/testdata/linux_write_to_outside_module.dmp \
|
||||
src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
|
||||
src/processor/testdata/linux_write_to_under_4k.dmp \
|
||||
src/processor/testdata/microdump-arm64.dmp \
|
||||
src/processor/testdata/microdump-arm.dmp \
|
||||
src/processor/testdata/microdump-mips32.dmp \
|
||||
src/processor/testdata/microdump-mips64.dmp \
|
||||
src/processor/testdata/microdump-multiple.dmp \
|
||||
src/processor/testdata/microdump.stackwalk-arm64.out \
|
||||
src/processor/testdata/microdump.stackwalk-arm.out \
|
||||
src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
|
||||
src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
|
||||
src/processor/testdata/microdump-x86.dmp \
|
||||
src/processor/testdata/minidump2.dmp \
|
||||
src/processor/testdata/minidump2.dump.out \
|
||||
src/processor/testdata/minidump2.stackwalk.machine_readable.out \
|
||||
src/processor/testdata/minidump2.stackwalk.out \
|
||||
src/processor/testdata/module0.out \
|
||||
src/processor/testdata/module1.out \
|
||||
src/processor/testdata/module2.out \
|
||||
src/processor/testdata/module3_bad.out \
|
||||
src/processor/testdata/module4_bad.out \
|
||||
src/processor/testdata/null_read_av.dmp \
|
||||
src/processor/testdata/null_write_av.dmp \
|
||||
src/processor/testdata/read_av_clobber_write.dmp \
|
||||
src/processor/testdata/read_av_conditional.dmp \
|
||||
src/processor/testdata/read_av_non_null.dmp \
|
||||
src/processor/testdata/stack_exhaustion.dmp \
|
||||
src/processor/testdata/write_av_non_null.dmp \
|
||||
src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
|
||||
src/processor/testdata/symbols/ld-2.13.so/C32AD7E235EA6112E02A5B9D6219C4850/ld-2.13.so.sym \
|
||||
src/processor/testdata/symbols/libc-2.13.so/F4F8DFCD5A5FB5A7CE64717E9E6AE3890/libc-2.13.so.sym \
|
||||
src/processor/testdata/symbols/libgcc_s.so.1/18B180F90887D8F8B5C35D185444AF4C0/libgcc_s.so.1.sym \
|
||||
src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
|
||||
src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
|
||||
src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
|
||||
src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
|
||||
src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
|
||||
src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
|
||||
src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
|
||||
src/processor/testdata/test_app.cc \
|
||||
src/tools/linux/dump_syms/Makefile \
|
||||
src/tools/linux/dump_syms/dump_syms.cc \
|
||||
src/tools/linux/symupload/Makefile \
|
||||
src/tools/linux/symupload/minidump_upload.cc \
|
||||
src/tools/linux/symupload/sym_upload.cc \
|
||||
src/testing/gtest/include/gtest/gtest.h \
|
||||
src/testing/gtest/include/gtest/gtest-death-test.h \
|
||||
src/testing/gtest/include/gtest/gtest-message.h \
|
||||
src/testing/gtest/include/gtest/gtest-param-test.h \
|
||||
src/testing/gtest/include/gtest/gtest-printers.h \
|
||||
src/testing/gtest/include/gtest/gtest-spi.h \
|
||||
src/testing/gtest/include/gtest/gtest-test-part.h \
|
||||
src/testing/gtest/include/gtest/gtest-typed-test.h \
|
||||
src/testing/gtest/include/gtest/gtest_pred_impl.h \
|
||||
src/testing/gtest/include/gtest/gtest_prod.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-filepath.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-internal.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-param-util.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-port.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-string.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-tuple.h \
|
||||
src/testing/gtest/include/gtest/internal/gtest-type-util.h \
|
||||
src/testing/gtest/src/gtest.cc \
|
||||
src/testing/gtest/src/gtest-death-test.cc \
|
||||
src/testing/gtest/src/gtest-filepath.cc \
|
||||
src/testing/gtest/src/gtest-internal-inl.h \
|
||||
src/testing/gtest/src/gtest-port.cc \
|
||||
src/testing/gtest/src/gtest-printers.cc \
|
||||
src/testing/gtest/src/gtest-test-part.cc \
|
||||
src/testing/gtest/src/gtest-typed-test.cc \
|
||||
src/testing/include/gmock/gmock.h \
|
||||
src/testing/include/gmock/gmock-actions.h \
|
||||
src/testing/include/gmock/gmock-cardinalities.h \
|
||||
src/testing/include/gmock/gmock-generated-actions.h \
|
||||
src/testing/include/gmock/gmock-generated-function-mockers.h \
|
||||
src/testing/include/gmock/gmock-generated-matchers.h \
|
||||
src/testing/include/gmock/gmock-generated-nice-strict.h \
|
||||
src/testing/include/gmock/gmock-matchers.h \
|
||||
src/testing/include/gmock/gmock-more-actions.h \
|
||||
src/testing/include/gmock/gmock-more-matchers.h \
|
||||
src/testing/include/gmock/gmock-spec-builders.h \
|
||||
src/testing/include/gmock/internal/gmock-generated-internal-utils.h \
|
||||
src/testing/include/gmock/internal/gmock-internal-utils.h \
|
||||
src/testing/include/gmock/internal/gmock-port.h \
|
||||
src/testing/src/gmock.cc \
|
||||
src/testing/src/gmock-cardinalities.cc \
|
||||
src/testing/src/gmock-internal-utils.cc \
|
||||
src/testing/src/gmock-matchers.cc \
|
||||
src/testing/src/gmock-spec-builders.cc \
|
||||
src/testing/src/gmock_main.cc \
|
||||
src/third_party/curl/COPYING \
|
||||
src/third_party/curl/curlbuild.h \
|
||||
src/third_party/curl/curl.h \
|
||||
src/third_party/curl/curlrules.h \
|
||||
src/third_party/curl/curlver.h \
|
||||
src/third_party/curl/easy.h \
|
||||
src/third_party/curl/mprintf.h \
|
||||
src/third_party/curl/multi.h \
|
||||
src/third_party/curl/stdcheaders.h \
|
||||
src/third_party/curl/typecheck-gcc.h \
|
||||
src/third_party/curl/types.h \
|
||||
src/third_party/mac_headers/architecture/byte_order.h \
|
||||
src/third_party/mac_headers/i386/_types.h \
|
||||
src/third_party/mac_headers/mach/boolean.h \
|
||||
src/third_party/mac_headers/mach/i386/boolean.h \
|
||||
src/third_party/mac_headers/mach/i386/vm_param.h \
|
||||
src/third_party/mac_headers/mach/i386/vm_types.h \
|
||||
src/third_party/mac_headers/mach/machine/boolean.h \
|
||||
src/third_party/mac_headers/mach/machine.h \
|
||||
src/third_party/mac_headers/mach/machine/thread_state.h \
|
||||
src/third_party/mac_headers/mach/machine/thread_status.h \
|
||||
src/third_party/mac_headers/mach/machine/vm_types.h \
|
||||
src/third_party/mac_headers/mach-o/arch.h \
|
||||
src/third_party/mac_headers/mach-o/fat.h \
|
||||
src/third_party/mac_headers/mach-o/loader.h \
|
||||
src/third_party/mac_headers/mach-o/nlist.h \
|
||||
src/third_party/mac_headers/mach/thread_status.h \
|
||||
src/third_party/mac_headers/mach/vm_prot.h \
|
||||
src/third_party/mac_headers/README \
|
||||
src/third_party/musl/README \
|
||||
src/third_party/musl/COPYRIGHT \
|
||||
src/third_party/musl/README.breakpad \
|
||||
src/third_party/musl/VERSION \
|
||||
src/third_party/musl/include/elf.h \
|
||||
src/tools/mac/crash_report/crash_report.mm \
|
||||
src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
|
||||
src/tools/mac/crash_report/on_demand_symbol_supplier.h \
|
||||
@ -3109,15 +3331,20 @@ EXTRA_DIST = \
|
||||
src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.cc \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.h \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.vcproj \
|
||||
src/tools/windows/converter/ms_symbol_server_converter.gyp \
|
||||
src/tools/windows/dump_syms/dump_syms.cc \
|
||||
src/tools/windows/dump_syms/dump_syms.vcproj \
|
||||
src/tools/windows/dump_syms/dump_syms.gyp \
|
||||
src/tools/windows/dump_syms/run_regtest.sh \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
|
||||
src/tools/windows/dump_syms/testdata/dump_syms_regtest64.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_reorder_bbs.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_reorder_funcs.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_stretched.sym \
|
||||
src/tools/windows/dump_syms/testdata/omap_stretched_filled.sym \
|
||||
src/tools/windows/symupload/symupload.cc \
|
||||
src/tools/windows/symupload/symupload.vcproj
|
||||
src/tools/windows/symupload/symupload.gyp
|
||||
|
||||
all: all-am
|
||||
|
||||
@ -3773,6 +4000,9 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT):
|
||||
src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
@ -3879,6 +4109,9 @@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT)
|
||||
src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/mac/$(am__dirstamp):
|
||||
@$(MKDIR_P) src/common/mac
|
||||
@: > src/common/mac/$(am__dirstamp)
|
||||
@ -4050,6 +4283,13 @@ src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.$(
|
||||
src/processor/proc_maps_linux_unittest$(EXEEXT): $(src_processor_proc_maps_linux_unittest_OBJECTS) $(src_processor_proc_maps_linux_unittest_DEPENDENCIES) $(EXTRA_src_processor_proc_maps_linux_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
|
||||
@rm -f src/processor/proc_maps_linux_unittest$(EXEEXT)
|
||||
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_proc_maps_linux_unittest_OBJECTS) $(src_processor_proc_maps_linux_unittest_LDADD) $(LIBS)
|
||||
src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.$(OBJEXT): \
|
||||
src/processor/$(am__dirstamp) \
|
||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||
|
||||
src/processor/range_map_shrink_down_unittest$(EXEEXT): $(src_processor_range_map_shrink_down_unittest_OBJECTS) $(src_processor_range_map_shrink_down_unittest_DEPENDENCIES) $(EXTRA_src_processor_range_map_shrink_down_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
|
||||
@rm -f src/processor/range_map_shrink_down_unittest$(EXEEXT)
|
||||
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_range_map_shrink_down_unittest_OBJECTS) $(src_processor_range_map_shrink_down_unittest_LDADD) $(LIBS)
|
||||
src/processor/range_map_unittest.$(OBJEXT): \
|
||||
src/processor/$(am__dirstamp) \
|
||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||
@ -4211,6 +4451,9 @@ src/common/dwarf/dwarf2diehandler.$(OBJEXT): \
|
||||
src/common/dwarf/dwarf2reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/dwarf/elf_reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/linux/crc32.$(OBJEXT): src/common/linux/$(am__dirstamp) \
|
||||
src/common/linux/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/linux/dump_symbols.$(OBJEXT): \
|
||||
@ -4268,6 +4511,9 @@ src/tools/linux/symupload/minidump_upload.$(OBJEXT): \
|
||||
src/tools/linux/symupload/minidump_upload$(EXEEXT): $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_DEPENDENCIES) $(EXTRA_src_tools_linux_symupload_minidump_upload_DEPENDENCIES) src/tools/linux/symupload/$(am__dirstamp)
|
||||
@rm -f src/tools/linux/symupload/minidump_upload$(EXEEXT)
|
||||
$(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_LDADD) $(LIBS)
|
||||
src/common/linux/symbol_upload.$(OBJEXT): \
|
||||
src/common/linux/$(am__dirstamp) \
|
||||
src/common/linux/$(DEPDIR)/$(am__dirstamp)
|
||||
src/tools/linux/symupload/sym_upload.$(OBJEXT): \
|
||||
src/tools/linux/symupload/$(am__dirstamp) \
|
||||
src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
|
||||
@ -4308,6 +4554,9 @@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT
|
||||
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT): \
|
||||
src/common/dwarf/$(am__dirstamp) \
|
||||
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT): \
|
||||
src/common/mac/$(am__dirstamp) \
|
||||
src/common/mac/$(DEPDIR)/$(am__dirstamp)
|
||||
@ -4458,6 +4707,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/bytereader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2diehandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/elf_reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Po@am__quote@
|
||||
@ -4466,13 +4716,16 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/crc32.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dump_symbols.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_core_dump.Po@am__quote@
|
||||
@ -4503,6 +4756,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/symbol_upload.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po@am__quote@
|
||||
@ -4572,6 +4826,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Po@am__quote@
|
||||
@ -5432,6 +5687,20 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj: src/common/dwarf/d
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
|
||||
|
||||
src/common/dwarf/src_common_dumper_unittest-elf_reader.o: src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_dumper_unittest-elf_reader.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
|
||||
|
||||
src/common/dwarf/src_common_dumper_unittest-elf_reader.obj: src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_dumper_unittest-elf_reader.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
|
||||
|
||||
src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o: src/common/dwarf/dwarf2reader_cfi_unittest.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o `test -f 'src/common/dwarf/dwarf2reader_cfi_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader_cfi_unittest.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po
|
||||
@ -5908,6 +6177,20 @@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj: src/comm
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
|
||||
|
||||
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o: src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
|
||||
|
||||
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj: src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
|
||||
|
||||
src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o: src/common/mac/arch_utilities.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po
|
||||
@ -6230,6 +6513,20 @@ src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.ob
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj `if test -f 'src/processor/proc_maps_linux_unittest.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux_unittest.cc'; fi`
|
||||
|
||||
src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o: src/processor/range_map_shrink_down_unittest.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o `test -f 'src/processor/range_map_shrink_down_unittest.cc' || echo '$(srcdir)/'`src/processor/range_map_shrink_down_unittest.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/range_map_shrink_down_unittest.cc' object='src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o `test -f 'src/processor/range_map_shrink_down_unittest.cc' || echo '$(srcdir)/'`src/processor/range_map_shrink_down_unittest.cc
|
||||
|
||||
src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj: src/processor/range_map_shrink_down_unittest.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj `if test -f 'src/processor/range_map_shrink_down_unittest.cc'; then $(CYGPATH_W) 'src/processor/range_map_shrink_down_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/range_map_shrink_down_unittest.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/range_map_shrink_down_unittest.cc' object='src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj `if test -f 'src/processor/range_map_shrink_down_unittest.cc'; then $(CYGPATH_W) 'src/processor/range_map_shrink_down_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/range_map_shrink_down_unittest.cc'; fi`
|
||||
|
||||
src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o: src/common/test_assembler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Po
|
||||
@ -6692,6 +6989,20 @@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj: src/com
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
|
||||
|
||||
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o: src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
|
||||
|
||||
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj: src/common/dwarf/elf_reader.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
|
||||
|
||||
src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o: src/common/mac/arch_utilities.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Po
|
||||
@ -7368,6 +7679,13 @@ src/processor/proc_maps_linux_unittest.log: src/processor/proc_maps_linux_unitte
|
||||
--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/range_map_shrink_down_unittest.log: src/processor/range_map_shrink_down_unittest$(EXEEXT)
|
||||
@p='src/processor/range_map_shrink_down_unittest$(EXEEXT)'; \
|
||||
b='src/processor/range_map_shrink_down_unittest'; \
|
||||
$(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/range_map_unittest.log: src/processor/range_map_unittest$(EXEEXT)
|
||||
@p='src/processor/range_map_unittest$(EXEEXT)'; \
|
||||
b='src/processor/range_map_unittest'; \
|
||||
|
@ -6,7 +6,7 @@ on Android, and later generate valid stack traces from the minidumps
|
||||
it generates.
|
||||
|
||||
This release supports ARM, x86 and MIPS based Android systems.
|
||||
This release requires NDK release r10c or higher.
|
||||
This release requires NDK release r11c or higher.
|
||||
|
||||
I. Building the client library:
|
||||
===============================
|
||||
@ -58,7 +58,7 @@ II. Using the client library in Android:
|
||||
========================================
|
||||
|
||||
The usage instructions are very similar to the Linux ones that are
|
||||
found at http://code.google.com/p/google-breakpad/wiki/LinuxStarterGuide
|
||||
found at https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/linux_starter_guide.md
|
||||
|
||||
1/ You need to include "client/linux/handler/exception_handler.h" from a C++
|
||||
source file.
|
||||
|
75
README.md
75
README.md
@ -8,42 +8,73 @@ crash-reporting system.
|
||||
* [Bugs](https://bugs.chromium.org/p/google-breakpad/)
|
||||
* Discussion/Questions: [google-breakpad-discuss@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-discuss)
|
||||
* Developer/Reviews: [google-breakpad-dev@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-dev)
|
||||
* Tests: [![Build Status](https://travis-ci.org/google/breakpad.svg?branch=master)](https://travis-ci.org/google/breakpad)
|
||||
|
||||
## Getting started in 32-bit mode (from trunk)
|
||||
## Getting started (from master)
|
||||
|
||||
```sh
|
||||
# Configure
|
||||
CXXFLAGS=-m32 CFLAGS=-m32 CPPFLAGS=-m32 ./configure
|
||||
# Build
|
||||
make
|
||||
# Test
|
||||
make check
|
||||
# Install
|
||||
make install
|
||||
```
|
||||
1. First, [download depot_tools](http://dev.chromium.org/developers/how-tos/install-depot-tools)
|
||||
and ensure that they're in your `PATH`.
|
||||
|
||||
2. Create a new directory for checking out the source code (it must be named
|
||||
breakpad).
|
||||
|
||||
```sh
|
||||
mkdir breakpad && cd breakpad
|
||||
```
|
||||
|
||||
3. Run the `fetch` tool from depot_tools to download all the source repos.
|
||||
|
||||
```sh
|
||||
fetch breakpad
|
||||
cd src
|
||||
```
|
||||
|
||||
4. Build the source.
|
||||
|
||||
```sh
|
||||
./configure && make
|
||||
```
|
||||
|
||||
You can also cd to another directory and run configure from there to build
|
||||
outside the source tree.
|
||||
|
||||
This will build the processor tools (`src/processor/minidump_stackwalk`,
|
||||
`src/processor/minidump_dump`, etc), and when building on Linux it will
|
||||
also build the client libraries and some tools
|
||||
(`src/tools/linux/dump_syms/dump_syms`,
|
||||
`src/tools/linux/md2core/minidump-2-core`, etc).
|
||||
|
||||
5. Optionally, run tests.
|
||||
|
||||
```sh
|
||||
make check
|
||||
```
|
||||
|
||||
6. Optionally, install the built libraries
|
||||
|
||||
```sh
|
||||
make install
|
||||
```
|
||||
|
||||
If you need to reconfigure your build be sure to run `make distclean` first.
|
||||
|
||||
## To request change review:
|
||||
To update an existing checkout to a newer revision, you can
|
||||
`git pull` as usual, but then you should run `gclient sync` to ensure that the
|
||||
dependent repos are up-to-date.
|
||||
|
||||
1. Get a copy of depot_tools repo.
|
||||
http://dev.chromium.org/developers/how-tos/install-depot-tools
|
||||
## To request change review
|
||||
|
||||
2. Create a new directory for checking out the source code.
|
||||
mkdir breakpad && cd breakpad
|
||||
1. Follow the steps above to get the source and build it.
|
||||
|
||||
3. Run the `fetch` tool from depot_tools to download all the source repos.
|
||||
`fetch breakpad`
|
||||
|
||||
4. Make changes. Build and test your changes.
|
||||
2. Make changes. Build and test your changes.
|
||||
For core code like processor use methods above.
|
||||
For linux/mac/windows, there are test targets in each project file.
|
||||
|
||||
5. Commit your changes to your local repo and upload them to the server.
|
||||
3. Commit your changes to your local repo and upload them to the server.
|
||||
http://dev.chromium.org/developers/contributing-code
|
||||
e.g. `git commit ... && git cl upload ...`
|
||||
You will be prompted for credential and a description.
|
||||
|
||||
6. At https://codereview.chromium.org/ you'll find your issue listed; click on
|
||||
4. At https://codereview.chromium.org/ you'll find your issue listed; click on
|
||||
it, and select Publish+Mail, and enter in the code reviewer and CC
|
||||
google-breakpad-dev@googlegroups.com
|
||||
|
@ -71,9 +71,12 @@ LOCAL_ARM_MODE := arm
|
||||
# List of client source files, directly taken from Makefile.am
|
||||
LOCAL_SRC_FILES := \
|
||||
src/client/linux/crash_generation/crash_generation_client.cc \
|
||||
src/client/linux/dump_writer_common/thread_info.cc \
|
||||
src/client/linux/dump_writer_common/ucontext_reader.cc \
|
||||
src/client/linux/handler/exception_handler.cc \
|
||||
src/client/linux/handler/minidump_descriptor.cc \
|
||||
src/client/linux/log/log.cc \
|
||||
src/client/linux/microdump_writer/microdump_writer.cc \
|
||||
src/client/linux/minidump_writer/linux_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
|
||||
src/client/linux/minidump_writer/minidump_writer.cc \
|
||||
|
@ -29,3 +29,4 @@
|
||||
|
||||
APP_STL := stlport_static
|
||||
APP_ABI := all
|
||||
APP_CXXFLAGS := -std=c++11 -D__STDC_LIMIT_MACROS
|
||||
|
@ -14,76 +14,85 @@ necessary to produce minidumps from an application.
|
||||
|
||||
First, configure your build process to link **libbreakpad\_client.a** into your
|
||||
binary, and set your include paths to include the **src** directory in the
|
||||
**google-breakpad** source tree. Next, include the exception handler header: ```
|
||||
|
||||
# include "client/linux/handler/exception_handler.h"
|
||||
**google-breakpad** source tree. Next, include the exception handler header:
|
||||
|
||||
```cpp
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
```
|
||||
|
||||
Now you can instantiate an `ExceptionHandler` object. Exception handling is active for the lifetime of the `ExceptionHandler` object, so you should instantiate it as early as possible in your application's startup process, and keep it alive for as close to shutdown as possible. To do anything useful, the `ExceptionHandler` constructor requires a path where it can write minidumps, as well as a callback function to receive information about minidumps that were written:
|
||||
```
|
||||
|
||||
```cpp
|
||||
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
|
||||
void* context, bool succeeded) { printf("Dump path: %s\n", descriptor.path());
|
||||
return succeeded; }
|
||||
void* context, bool succeeded) {
|
||||
printf("Dump path: %s\n", descriptor.path());
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void crash() { volatile int* a = (int*)(NULL); *a = 1; }
|
||||
|
||||
int main(int argc, char* argv[]) { google_breakpad::MinidumpDescriptor
|
||||
descriptor("/tmp"); google_breakpad::ExceptionHandler eh(descriptor, NULL,
|
||||
dumpCallback, NULL, true, -1); crash(); return 0; } ```
|
||||
int main(int argc, char* argv[]) {
|
||||
google_breakpad::MinidumpDescriptor descriptor("/tmp");
|
||||
google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
|
||||
crash();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compiling and running this example should produce a minidump file in /tmp, and
|
||||
it should print the minidump filename before exiting. You can read more about
|
||||
the other parameters to the `ExceptionHandler` constructor <a
|
||||
href='http://code.google.com/p/google-breakpad/source/browse/trunk/src/client/linux/handler/exception_handler.h'>in
|
||||
the exception_handler.h source file</a>.
|
||||
the other parameters to the `ExceptionHandler` constructor [in the exception_handler.h source file][1].
|
||||
|
||||
[1]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/client/linux/handler/exception_handler.h
|
||||
|
||||
**Note**: You should do as little work as possible in the callback function.
|
||||
Your application is in an unsafe state. It may not be safe to allocate memory or
|
||||
call functions from other shared libraries. The safest thing to do is `fork` and
|
||||
`exec` a new process to do any work you need to do. If you must do some work in
|
||||
the callback, the Breakpad source contains <a
|
||||
href='http://code.google.com/p/google-breakpad/source/browse/trunk/src/common/linux/linux_libc_support.h'>some
|
||||
simple reimplementations of libc functions</a>, to avoid calling directly into
|
||||
libc, as well as <a href='http://code.google.com/p/linux-syscall-support/'>a
|
||||
header file for making Linux system calls</a> (in **src/third\_party/lss**) to
|
||||
avoid calling into other shared libraries.
|
||||
the callback, the Breakpad source contains [some simple reimplementations of libc functions][2], to avoid calling directly into
|
||||
libc, as well as [a header file for making Linux system calls][3] (in **src/third\_party/lss**) to avoid calling into other shared libraries.
|
||||
|
||||
[2]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/common/linux/linux_libc_support.h
|
||||
[3]: https://chromium.googlesource.com/linux-syscall-support/+/master
|
||||
|
||||
## Sending the minidump file
|
||||
|
||||
In a real application, you would want to handle the minidump in some way, likely
|
||||
by sending it to a server for analysis. The Breakpad source tree contains <a
|
||||
href='http://code.google.com/p/google-breakpad/source/browse/#svn/trunk/src/common/linux'>some
|
||||
HTTP upload source</a> that you might find useful, as well as <a
|
||||
href='http://code.google.com/p/google-breakpad/source/browse/#svn/trunk/src/tools/linux/symupload'>a
|
||||
minidump upload tool</a>.
|
||||
by sending it to a server for analysis. The Breakpad source tree contains [some
|
||||
HTTP upload source][4] that you might find useful, as well as [a minidump upload tool][5].
|
||||
|
||||
[4]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/common/linux/http_upload.h
|
||||
[5]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/tools/linux/symupload/minidump_upload.cc
|
||||
|
||||
## Producing symbols for your application
|
||||
|
||||
To produce useful stack traces, Breakpad requires you to convert the debugging
|
||||
symbols in your binaries to <a
|
||||
href='http://code.google.com/p/google-breakpad/wiki/SymbolFiles'>text-format
|
||||
symbol files</a>. First, ensure that you've compiled your binaries with `-g` to
|
||||
symbols in your binaries to [text-format symbol files][6]. First, ensure that you've compiled your binaries with `-g` to
|
||||
include debugging symbols. Next, compile the `dump_syms` tool by running
|
||||
`configure && make` in the Breakpad source directory. Next, run `dump_syms` on
|
||||
your binaries to produce the text-format symbols. For example, if your main
|
||||
binary was named `test`: `$ google-breakpad/src/tools/linux/dump_syms/dump_syms
|
||||
./test > test.sym
|
||||
`
|
||||
binary was named `test`:
|
||||
|
||||
[6]: https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
|
||||
|
||||
```
|
||||
$ google-breakpad/src/tools/linux/dump_syms/dump_syms ./test > test.sym
|
||||
```
|
||||
|
||||
In order to use these symbols with the `minidump_stackwalk` tool, you will need
|
||||
to place them in a specific directory structure. The first line of the symbol
|
||||
file contains the information you need to produce this directory structure, for
|
||||
example (your output will vary): `$ head -n1 test.sym MODULE Linux x86_64
|
||||
6EDC6ACDB282125843FD59DA9C81BD830 test $ mkdir -p
|
||||
./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830 $ mv test.sym
|
||||
./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
|
||||
`
|
||||
example (your output will vary):
|
||||
|
||||
You may also find the <a
|
||||
href='http://mxr.mozilla.org/mozilla-central/source/toolkit/crashreporter/tools/symbolstore.py'>symbolstore.py</a>
|
||||
script in the Mozilla repository useful, as it encapsulates these steps.
|
||||
```
|
||||
$ head -n1 test.sym MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test
|
||||
$ mkdir -p ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
|
||||
$ mv test.sym ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
|
||||
```
|
||||
|
||||
You may also find the [symbolstore.py][7] script in the Mozilla repository useful, as it encapsulates these steps.
|
||||
|
||||
[7]: https://dxr.mozilla.org/mozilla-central/source/toolkit/crashreporter/tools/symbolstore.py
|
||||
|
||||
## Processing the minidump to produce a stack trace
|
||||
|
||||
@ -92,6 +101,10 @@ plus its corresponding text-format symbols and produce a symbolized stacktrace.
|
||||
It should be in the **google-breakpad/src/processor** directory if you compiled
|
||||
the Breakpad source using the directions above. Simply pass it the minidump and
|
||||
the symbol path as commandline parameters:
|
||||
`google-breakpad/src/processor/minidump_stackwalk minidump.dmp ./symbols
|
||||
` It produces verbose output on stderr, and the stacktrace on stdout, so you may
|
||||
|
||||
```
|
||||
$ google-breakpad/src/processor/minidump_stackwalk minidump.dmp ./symbols
|
||||
```
|
||||
|
||||
It produces verbose output on stderr, and the stacktrace on stdout, so you may
|
||||
want to redirect stderr.
|
||||
|
43
scripts/travis-build.sh
Executable file
43
scripts/travis-build.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
setup_env() {
|
||||
# Travis sets CC/CXX to the system toolchain, so our .travis.yml
|
||||
# exports USE_{CC,CXX} for this script to use.
|
||||
if [ -n "$USE_CC" ]; then
|
||||
export CC=$USE_CC
|
||||
fi
|
||||
if [ -n "$USE_CXX" ]; then
|
||||
export CXX=$USE_CXX
|
||||
fi
|
||||
# Use -jN for faster builds. Travis build machines under Docker
|
||||
# have a lot of cores, but are memory-limited, so the kernel
|
||||
# will OOM if we try to use them all, so use at most 4.
|
||||
# See https://github.com/travis-ci/travis-ci/issues/1972
|
||||
export NCPUS=$(getconf _NPROCESSORS_ONLN)
|
||||
export JOBS=$(( $NCPUS < 4 ? $NCPUS : 4 ))
|
||||
}
|
||||
|
||||
# Do an in-tree build and make sure tests pass.
|
||||
build() {
|
||||
./configure
|
||||
make -j${JOBS} check VERBOSE=1
|
||||
make distclean
|
||||
}
|
||||
|
||||
# Do an out-of-tree build and make sure we can create a release tarball.
|
||||
build_out_of_tree() {
|
||||
mkdir -p build/native
|
||||
cd build/native
|
||||
../../configure
|
||||
make -j${JOBS} distcheck VERBOSE=1
|
||||
}
|
||||
|
||||
main() {
|
||||
setup_env
|
||||
build
|
||||
build_out_of_tree
|
||||
}
|
||||
|
||||
main "$@"
|
24
scripts/travis-checkout.sh
Executable file
24
scripts/travis-checkout.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
get_depot_tools() {
|
||||
cd
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
PATH="$HOME/depot_tools:$PATH"
|
||||
}
|
||||
|
||||
gclient_sync() {
|
||||
# Rename the source dir to match what gclient expects.
|
||||
srcdir=$(basename "$TRAVIS_BUILD_DIR")
|
||||
cd "${TRAVIS_BUILD_DIR}"/..
|
||||
mv "${srcdir}" src
|
||||
gclient config --unmanaged https://github.com/google/breakpad.git
|
||||
gclient sync
|
||||
}
|
||||
|
||||
main() {
|
||||
get_depot_tools
|
||||
gclient_sync
|
||||
}
|
||||
|
||||
main "$@"
|
@ -118,7 +118,7 @@ namespace {
|
||||
// all these signals must be Core (see man 7 signal) because we rethrow the
|
||||
// signal after handling it and expect that it'll be fatal.
|
||||
const int kExceptionSignals[] = {
|
||||
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
|
||||
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP
|
||||
};
|
||||
const int kNumHandledSignals =
|
||||
sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#include "client/linux/minidump_writer/minidump_writer.h"
|
||||
#include "common/linux/eintr_wrapper.h"
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/linux/ignore_ret.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/tests/auto_tempdir.h"
|
||||
@ -94,10 +93,6 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Length of a formatted GUID string =
|
||||
// sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator)
|
||||
const int kGUIDStringSize = 37;
|
||||
|
||||
void sigchld_handler(int signo) { }
|
||||
|
||||
int CreateTMPFile(const string& dir, string* path) {
|
||||
@ -817,19 +812,7 @@ TEST(ExceptionHandlerTest, ModuleInfo) {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||
};
|
||||
char module_identifier_buffer[kGUIDStringSize];
|
||||
FileID::ConvertIdentifierToString(kModuleGUID,
|
||||
module_identifier_buffer,
|
||||
sizeof(module_identifier_buffer));
|
||||
string module_identifier(module_identifier_buffer);
|
||||
// Strip out dashes
|
||||
size_t pos;
|
||||
while ((pos = module_identifier.find('-')) != string::npos) {
|
||||
module_identifier.erase(pos, 1);
|
||||
}
|
||||
// And append a zero, because module IDs include an "age" field
|
||||
// which is always zero on Linux.
|
||||
module_identifier += "0";
|
||||
const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
|
||||
|
||||
// Get some memory.
|
||||
char* memory =
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
#include "client/linux/microdump_writer/microdump_writer.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "client/linux/dump_writer_common/thread_info.h"
|
||||
@ -40,11 +42,15 @@
|
||||
#include "client/linux/handler/microdump_extra_info.h"
|
||||
#include "client/linux/log/log.h"
|
||||
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/memory.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using google_breakpad::auto_wasteful_vector;
|
||||
using google_breakpad::ExceptionHandler;
|
||||
using google_breakpad::kDefaultBuildIdSize;
|
||||
using google_breakpad::LinuxDumper;
|
||||
using google_breakpad::LinuxPtraceDumper;
|
||||
using google_breakpad::MappingInfo;
|
||||
@ -56,6 +62,72 @@ using google_breakpad::UContextReader;
|
||||
|
||||
const size_t kLineBufferSize = 2048;
|
||||
|
||||
#if !defined(__LP64__)
|
||||
// The following are only used by DumpFreeSpace, so need to be compiled
|
||||
// in conditionally in the same way.
|
||||
|
||||
template <typename Dst, typename Src>
|
||||
Dst saturated_cast(Src src) {
|
||||
if (src >= std::numeric_limits<Dst>::max())
|
||||
return std::numeric_limits<Dst>::max();
|
||||
if (src <= std::numeric_limits<Dst>::min())
|
||||
return std::numeric_limits<Dst>::min();
|
||||
return static_cast<Dst>(src);
|
||||
}
|
||||
|
||||
int Log2Floor(uint64_t n) {
|
||||
// Copied from chromium src/base/bits.h
|
||||
if (n == 0)
|
||||
return -1;
|
||||
int log = 0;
|
||||
uint64_t value = n;
|
||||
for (int i = 5; i >= 0; --i) {
|
||||
int shift = (1 << i);
|
||||
uint64_t x = value >> shift;
|
||||
if (x != 0) {
|
||||
value = x;
|
||||
log += shift;
|
||||
}
|
||||
}
|
||||
assert(value == 1u);
|
||||
return log;
|
||||
}
|
||||
|
||||
bool MappingsAreAdjacent(const MappingInfo& a, const MappingInfo& b) {
|
||||
// Because of load biasing, we can end up with a situation where two
|
||||
// mappings actually overlap. So we will define adjacency to also include a
|
||||
// b start address that lies within a's address range (including starting
|
||||
// immediately after a).
|
||||
// Because load biasing only ever moves the start address backwards, the end
|
||||
// address should still increase.
|
||||
return a.start_addr <= b.start_addr && a.start_addr + a.size >= b.start_addr;
|
||||
}
|
||||
|
||||
bool MappingLessThan(const MappingInfo* a, const MappingInfo* b) {
|
||||
// Return true if mapping a is before mapping b.
|
||||
// For the same reason (load biasing) we compare end addresses, which - unlike
|
||||
// start addresses - will not have been modified.
|
||||
return a->start_addr + a->size < b->start_addr + b->size;
|
||||
}
|
||||
|
||||
size_t NextOrderedMapping(
|
||||
const google_breakpad::wasteful_vector<MappingInfo*>& mappings,
|
||||
size_t curr) {
|
||||
// Find the mapping that directly follows mappings[curr].
|
||||
// If no such mapping exists, return |invalid| to indicate this.
|
||||
const size_t invalid = std::numeric_limits<size_t>::max();
|
||||
size_t best = invalid;
|
||||
for (size_t next = 0; next < mappings.size(); ++next) {
|
||||
if (MappingLessThan(mappings[curr], mappings[next]) &&
|
||||
(best == invalid || MappingLessThan(mappings[next], mappings[best]))) {
|
||||
best = next;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
#endif // !__LP64__
|
||||
|
||||
class MicrodumpWriter {
|
||||
public:
|
||||
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
|
||||
@ -93,6 +165,9 @@ class MicrodumpWriter {
|
||||
DumpProductInformation();
|
||||
DumpOSInformation();
|
||||
DumpGPUInformation();
|
||||
#if !defined(__LP64__)
|
||||
DumpFreeSpace();
|
||||
#endif
|
||||
success = DumpCrashingThread();
|
||||
if (success)
|
||||
success = DumpMappings();
|
||||
@ -336,21 +411,31 @@ class MicrodumpWriter {
|
||||
bool member,
|
||||
unsigned int mapping_id,
|
||||
const uint8_t* identifier) {
|
||||
MDGUID module_identifier;
|
||||
|
||||
auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
|
||||
dumper_->allocator());
|
||||
|
||||
if (identifier) {
|
||||
// GUID was provided by caller.
|
||||
my_memcpy(&module_identifier, identifier, sizeof(MDGUID));
|
||||
identifier_bytes.insert(identifier_bytes.end(),
|
||||
identifier,
|
||||
identifier + sizeof(MDGUID));
|
||||
} else {
|
||||
dumper_->ElfFileIdentifierForMapping(
|
||||
mapping,
|
||||
member,
|
||||
mapping_id,
|
||||
reinterpret_cast<uint8_t*>(&module_identifier));
|
||||
identifier_bytes);
|
||||
}
|
||||
|
||||
// Copy as many bytes of |identifier| as will fit into a MDGUID
|
||||
MDGUID module_identifier = {0};
|
||||
memcpy(&module_identifier, &identifier_bytes[0],
|
||||
std::min(sizeof(MDGUID), identifier_bytes.size()));
|
||||
|
||||
char file_name[NAME_MAX];
|
||||
char file_path[NAME_MAX];
|
||||
LinuxDumper::GetMappingEffectiveNameAndPath(
|
||||
dumper_->GetMappingEffectiveNameAndPath(
|
||||
mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
|
||||
|
||||
LogAppend("M ");
|
||||
@ -376,6 +461,80 @@ class MicrodumpWriter {
|
||||
LogCommitLine();
|
||||
}
|
||||
|
||||
#if !defined(__LP64__)
|
||||
void DumpFreeSpace() {
|
||||
const google_breakpad::wasteful_vector<MappingInfo*>& mappings =
|
||||
dumper_->mappings();
|
||||
if (mappings.size() == 0) return;
|
||||
|
||||
// This is complicated by the fact that mappings is not in order. It should
|
||||
// be mostly in order, however the mapping that contains the entry point for
|
||||
// the process is always at the front of the vector.
|
||||
|
||||
static const int HBITS = sizeof(size_t) * 8;
|
||||
size_t hole_histogram[HBITS];
|
||||
my_memset(hole_histogram, 0, sizeof(hole_histogram));
|
||||
|
||||
// Find the lowest address mapping.
|
||||
size_t curr = 0;
|
||||
for (size_t i = 1; i < mappings.size(); ++i) {
|
||||
if (mappings[i]->start_addr < mappings[curr]->start_addr) curr = i;
|
||||
}
|
||||
|
||||
uintptr_t lo_addr = mappings[curr]->start_addr;
|
||||
|
||||
size_t hole_cnt = 0;
|
||||
size_t hole_max = 0;
|
||||
size_t hole_sum = 0;
|
||||
|
||||
while (true) {
|
||||
// Skip to the end of an adjacent run of mappings. This is an optimization
|
||||
// for the fact that mappings is mostly sorted.
|
||||
while (curr != mappings.size() - 1 &&
|
||||
MappingsAreAdjacent(*mappings[curr], *mappings[curr + 1])) {
|
||||
++curr;
|
||||
}
|
||||
|
||||
size_t next = NextOrderedMapping(mappings, curr);
|
||||
if (next == std::numeric_limits<size_t>::max())
|
||||
break;
|
||||
|
||||
uintptr_t hole_lo = mappings[curr]->start_addr + mappings[curr]->size;
|
||||
uintptr_t hole_hi = mappings[next]->start_addr;
|
||||
|
||||
if (hole_hi > hole_lo) {
|
||||
size_t hole_sz = hole_hi - hole_lo;
|
||||
hole_sum += hole_sz;
|
||||
hole_max = std::max(hole_sz, hole_max);
|
||||
++hole_cnt;
|
||||
++hole_histogram[Log2Floor(hole_sz)];
|
||||
}
|
||||
curr = next;
|
||||
}
|
||||
|
||||
uintptr_t hi_addr = mappings[curr]->start_addr + mappings[curr]->size;
|
||||
|
||||
LogAppend("H ");
|
||||
LogAppend(lo_addr);
|
||||
LogAppend(" ");
|
||||
LogAppend(hi_addr);
|
||||
LogAppend(" ");
|
||||
LogAppend(saturated_cast<uint16_t>(hole_cnt));
|
||||
LogAppend(" ");
|
||||
LogAppend(hole_max);
|
||||
LogAppend(" ");
|
||||
LogAppend(hole_sum);
|
||||
for (unsigned int i = 0; i < HBITS; ++i) {
|
||||
if (!hole_histogram[i]) continue;
|
||||
LogAppend(" ");
|
||||
LogAppend(saturated_cast<uint8_t>(i));
|
||||
LogAppend(":");
|
||||
LogAppend(saturated_cast<uint8_t>(hole_histogram[i]));
|
||||
}
|
||||
LogCommitLine();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write information about the mappings in effect.
|
||||
bool DumpMappings() {
|
||||
// First write all the mappings from the dumper
|
||||
|
@ -49,8 +49,9 @@ namespace google_breakpad {
|
||||
|
||||
LinuxCoreDumper::LinuxCoreDumper(pid_t pid,
|
||||
const char* core_path,
|
||||
const char* procfs_path)
|
||||
: LinuxDumper(pid),
|
||||
const char* procfs_path,
|
||||
const char* root_prefix)
|
||||
: LinuxDumper(pid, root_prefix),
|
||||
core_path_(core_path),
|
||||
procfs_path_(procfs_path),
|
||||
thread_infos_(&allocator_, 8) {
|
||||
|
@ -47,7 +47,9 @@ class LinuxCoreDumper : public LinuxDumper {
|
||||
// its proc files at |procfs_path|. If |procfs_path| is a copy of
|
||||
// /proc/<pid>, it should contain the following files:
|
||||
// auxv, cmdline, environ, exe, maps, status
|
||||
LinuxCoreDumper(pid_t pid, const char* core_path, const char* procfs_path);
|
||||
// See LinuxDumper for the purpose of |root_prefix|.
|
||||
LinuxCoreDumper(pid_t pid, const char* core_path, const char* procfs_path,
|
||||
const char* root_prefix = "");
|
||||
|
||||
// Implements LinuxDumper::BuildProcPath().
|
||||
// Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
|
||||
|
@ -39,6 +39,16 @@
|
||||
|
||||
using namespace google_breakpad;
|
||||
|
||||
TEST(LinuxCoreDumperTest, GetMappingAbsolutePath) {
|
||||
const LinuxCoreDumper dumper(getpid(), "core", "/tmp", "/mnt/root");
|
||||
const MappingInfo mapping = { 0, 0, 0, false, "/usr/lib/libc.so" };
|
||||
|
||||
char path[PATH_MAX];
|
||||
dumper.GetMappingAbsolutePath(mapping, path);
|
||||
|
||||
EXPECT_STREQ("/mnt/root/usr/lib/libc.so", path);
|
||||
}
|
||||
|
||||
TEST(LinuxCoreDumperTest, BuildProcPath) {
|
||||
const pid_t pid = getpid();
|
||||
const char procfs_path[] = "/procfs_copy";
|
||||
|
@ -70,7 +70,6 @@ static const int DT_ANDROID_RELA = DT_LOOS + 4;
|
||||
|
||||
static const char kMappedFileUnsafePrefix[] = "/dev/";
|
||||
static const char kDeletedSuffix[] = " (deleted)";
|
||||
static const char kReservedFlags[] = " ---p";
|
||||
|
||||
inline static bool IsMappedFileOpenUnsafe(
|
||||
const google_breakpad::MappingInfo& mapping) {
|
||||
@ -88,14 +87,16 @@ namespace google_breakpad {
|
||||
// All interesting auvx entry types are below AT_SYSINFO_EHDR
|
||||
#define AT_MAX AT_SYSINFO_EHDR
|
||||
|
||||
LinuxDumper::LinuxDumper(pid_t pid)
|
||||
LinuxDumper::LinuxDumper(pid_t pid, const char* root_prefix)
|
||||
: pid_(pid),
|
||||
root_prefix_(root_prefix),
|
||||
crash_address_(0),
|
||||
crash_signal_(0),
|
||||
crash_thread_(pid),
|
||||
threads_(&allocator_, 8),
|
||||
mappings_(&allocator_),
|
||||
auxv_(&allocator_, AT_MAX + 1) {
|
||||
assert(root_prefix_ && my_strlen(root_prefix_) < PATH_MAX);
|
||||
// The passed-in size to the constructor (above) is only a hint.
|
||||
// Must call .resize() to do actual initialization of the elements.
|
||||
auxv_.resize(AT_MAX + 1);
|
||||
@ -119,9 +120,8 @@ bool
|
||||
LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
bool member,
|
||||
unsigned int mapping_id,
|
||||
uint8_t identifier[sizeof(MDGUID)]) {
|
||||
wasteful_vector<uint8_t>& identifier) {
|
||||
assert(!member || mapping_id < mappings_.size());
|
||||
my_memset(identifier, 0, sizeof(MDGUID));
|
||||
if (IsMappedFileOpenUnsafe(mapping))
|
||||
return false;
|
||||
|
||||
@ -139,14 +139,9 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier);
|
||||
}
|
||||
|
||||
char filename[NAME_MAX];
|
||||
size_t filename_len = my_strlen(mapping.name);
|
||||
if (filename_len >= NAME_MAX) {
|
||||
assert(false);
|
||||
char filename[PATH_MAX];
|
||||
if (!GetMappingAbsolutePath(mapping, filename))
|
||||
return false;
|
||||
}
|
||||
my_memcpy(filename, mapping.name, filename_len);
|
||||
filename[filename_len] = '\0';
|
||||
bool filename_modified = HandleDeletedFileInMapping(filename);
|
||||
|
||||
MemoryMappedFile mapped_file(filename, mapping.offset);
|
||||
@ -156,13 +151,19 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
bool success =
|
||||
FileID::ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
|
||||
if (success && member && filename_modified) {
|
||||
mappings_[mapping_id]->name[filename_len -
|
||||
mappings_[mapping_id]->name[my_strlen(mapping.name) -
|
||||
sizeof(kDeletedSuffix) + 1] = '\0';
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool LinuxDumper::GetMappingAbsolutePath(const MappingInfo& mapping,
|
||||
char path[PATH_MAX]) const {
|
||||
return my_strlcpy(path, root_prefix_, PATH_MAX) < PATH_MAX &&
|
||||
my_strlcat(path, mapping.name, PATH_MAX) < PATH_MAX;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool ElfFileSoNameFromMappedFile(
|
||||
const void* elf_base, char* soname, size_t soname_size) {
|
||||
@ -212,23 +213,16 @@ bool ElfFileSoNameFromMappedFile(
|
||||
// for |mapping|. If the SONAME is found copy it into the passed buffer
|
||||
// |soname| and return true. The size of the buffer is |soname_size|.
|
||||
// The SONAME will be truncated if it is too long to fit in the buffer.
|
||||
bool ElfFileSoName(
|
||||
bool ElfFileSoName(const LinuxDumper& dumper,
|
||||
const MappingInfo& mapping, char* soname, size_t soname_size) {
|
||||
if (IsMappedFileOpenUnsafe(mapping)) {
|
||||
// Not safe
|
||||
return false;
|
||||
}
|
||||
|
||||
char filename[NAME_MAX];
|
||||
size_t filename_len = my_strlen(mapping.name);
|
||||
if (filename_len >= NAME_MAX) {
|
||||
assert(false);
|
||||
// name too long
|
||||
char filename[PATH_MAX];
|
||||
if (!dumper.GetMappingAbsolutePath(mapping, filename))
|
||||
return false;
|
||||
}
|
||||
|
||||
my_memcpy(filename, mapping.name, filename_len);
|
||||
filename[filename_len] = '\0';
|
||||
|
||||
MemoryMappedFile mapped_file(filename, mapping.offset);
|
||||
if (!mapped_file.data() || mapped_file.size() < SELFMAG) {
|
||||
@ -242,7 +236,6 @@ bool ElfFileSoName(
|
||||
} // namespace
|
||||
|
||||
|
||||
// static
|
||||
void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
|
||||
char* file_path,
|
||||
size_t file_path_size,
|
||||
@ -255,8 +248,10 @@ void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
|
||||
// apk on Android). We try to find the name of the shared object (SONAME) by
|
||||
// looking in the file for ELF sections.
|
||||
bool mapped_from_archive = false;
|
||||
if (mapping.exec && mapping.offset != 0)
|
||||
mapped_from_archive = ElfFileSoName(mapping, file_name, file_name_size);
|
||||
if (mapping.exec && mapping.offset != 0) {
|
||||
mapped_from_archive =
|
||||
ElfFileSoName(*this, mapping, file_name, file_name_size);
|
||||
}
|
||||
|
||||
if (mapped_from_archive) {
|
||||
// Some tools (e.g., stackwalk) extract the basename from the pathname. In
|
||||
@ -354,24 +349,8 @@ bool LinuxDumper::EnumerateMappings() {
|
||||
MappingInfo* module = mappings_.back();
|
||||
if ((start_addr == module->start_addr + module->size) &&
|
||||
(my_strlen(name) == my_strlen(module->name)) &&
|
||||
(my_strncmp(name, module->name, my_strlen(name)) == 0)) {
|
||||
module->size = end_addr - module->start_addr;
|
||||
line_reader->PopLine(line_len);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Also merge mappings that result from address ranges that the
|
||||
// linker reserved but which a loaded library did not use. These
|
||||
// appear as an anonymous private mapping with no access flags set
|
||||
// and which directly follow an executable mapping.
|
||||
if (!name && !mappings_.empty()) {
|
||||
MappingInfo* module = mappings_.back();
|
||||
if ((start_addr == module->start_addr + module->size) &&
|
||||
module->exec &&
|
||||
module->name[0] == '/' &&
|
||||
offset == 0 && my_strncmp(i2,
|
||||
kReservedFlags,
|
||||
sizeof(kReservedFlags) - 1) == 0) {
|
||||
(my_strncmp(name, module->name, my_strlen(name)) == 0) &&
|
||||
(exec == module->exec)) {
|
||||
module->size = end_addr - module->start_addr;
|
||||
line_reader->PopLine(line_len);
|
||||
continue;
|
||||
@ -580,10 +559,13 @@ bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
|
||||
|
||||
// Check |path| against the /proc/pid/exe 'symlink'.
|
||||
char exe_link[NAME_MAX];
|
||||
char new_path[NAME_MAX];
|
||||
if (!BuildProcPath(exe_link, pid_, "exe"))
|
||||
return false;
|
||||
if (!SafeReadLink(exe_link, new_path))
|
||||
MappingInfo new_mapping = {0};
|
||||
if (!SafeReadLink(exe_link, new_mapping.name))
|
||||
return false;
|
||||
char new_path[PATH_MAX];
|
||||
if (!GetMappingAbsolutePath(new_mapping, new_path))
|
||||
return false;
|
||||
if (my_strcmp(path, new_path) != 0)
|
||||
return false;
|
||||
|
@ -49,6 +49,7 @@
|
||||
|
||||
#include "client/linux/dump_writer_common/mapping_info.h"
|
||||
#include "client/linux/dump_writer_common/thread_info.h"
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/memory.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
@ -72,7 +73,9 @@ const char kLinuxGateLibraryName[] = "linux-gate.so";
|
||||
|
||||
class LinuxDumper {
|
||||
public:
|
||||
explicit LinuxDumper(pid_t pid);
|
||||
// The |root_prefix| is prepended to mapping paths before opening them, which
|
||||
// is useful if the crash originates from a chroot.
|
||||
explicit LinuxDumper(pid_t pid, const char* root_prefix = "");
|
||||
|
||||
virtual ~LinuxDumper();
|
||||
|
||||
@ -127,7 +130,7 @@ class LinuxDumper {
|
||||
bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
bool member,
|
||||
unsigned int mapping_id,
|
||||
uint8_t identifier[sizeof(MDGUID)]);
|
||||
wasteful_vector<uint8_t>& identifier);
|
||||
|
||||
uintptr_t crash_address() const { return crash_address_; }
|
||||
void set_crash_address(uintptr_t crash_address) {
|
||||
@ -140,16 +143,21 @@ class LinuxDumper {
|
||||
pid_t crash_thread() const { return crash_thread_; }
|
||||
void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
|
||||
|
||||
// Concatenates the |root_prefix_| and |mapping| path. Writes into |path| and
|
||||
// returns true unless the string is too long.
|
||||
bool GetMappingAbsolutePath(const MappingInfo& mapping,
|
||||
char path[PATH_MAX]) const;
|
||||
|
||||
// Extracts the effective path and file name of from |mapping|. In most cases
|
||||
// the effective name/path are just the mapping's path and basename. In some
|
||||
// other cases, however, a library can be mapped from an archive (e.g., when
|
||||
// loading .so libs from an apk on Android) and this method is able to
|
||||
// reconstruct the original file name.
|
||||
static void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
|
||||
char* file_path,
|
||||
size_t file_path_size,
|
||||
char* file_name,
|
||||
size_t file_name_size);
|
||||
void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
|
||||
char* file_path,
|
||||
size_t file_path_size,
|
||||
char* file_name,
|
||||
size_t file_name_size);
|
||||
|
||||
protected:
|
||||
bool ReadAuxv();
|
||||
@ -172,6 +180,9 @@ class LinuxDumper {
|
||||
// ID of the crashed process.
|
||||
const pid_t pid_;
|
||||
|
||||
// Path of the root directory to which mapping paths are relative.
|
||||
const char* const root_prefix_;
|
||||
|
||||
// Virtual address at which the process crashed.
|
||||
uintptr_t crash_address_;
|
||||
|
||||
|
@ -66,6 +66,7 @@ using namespace google_breakpad;
|
||||
|
||||
namespace {
|
||||
|
||||
typedef wasteful_vector<uint8_t> id_vector;
|
||||
typedef testing::Test LinuxPtraceDumperTest;
|
||||
|
||||
/* Fixture for running tests in a child process. */
|
||||
@ -105,11 +106,17 @@ class LinuxPtraceDumperChildTest : public testing::Test {
|
||||
* This is achieved by defining a TestBody macro further below.
|
||||
*/
|
||||
virtual void RealTestBody() = 0;
|
||||
|
||||
id_vector make_vector() {
|
||||
return id_vector(&allocator, kDefaultBuildIdSize);
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kFatalFailure = 1;
|
||||
static const int kNonFatalFailure = 2;
|
||||
|
||||
pid_t child_pid_;
|
||||
PageAllocator allocator;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -310,14 +317,15 @@ TEST_F(LinuxPtraceDumperChildTest, LinuxGateMappingID) {
|
||||
|
||||
// Need to suspend the child so ptrace actually works.
|
||||
ASSERT_TRUE(dumper.ThreadsSuspend());
|
||||
uint8_t identifier[sizeof(MDGUID)];
|
||||
id_vector identifier(make_vector());
|
||||
ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index],
|
||||
true,
|
||||
index,
|
||||
identifier));
|
||||
uint8_t empty_identifier[sizeof(MDGUID)];
|
||||
memset(empty_identifier, 0, sizeof(empty_identifier));
|
||||
EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier)));
|
||||
|
||||
id_vector empty_identifier(make_vector());
|
||||
empty_identifier.resize(kDefaultBuildIdSize, 0);
|
||||
EXPECT_NE(empty_identifier, identifier);
|
||||
EXPECT_TRUE(dumper.ThreadsResume());
|
||||
}
|
||||
#endif
|
||||
@ -343,19 +351,18 @@ TEST_F(LinuxPtraceDumperChildTest, FileIDsMatch) {
|
||||
}
|
||||
ASSERT_TRUE(found_exe);
|
||||
|
||||
uint8_t identifier1[sizeof(MDGUID)];
|
||||
uint8_t identifier2[sizeof(MDGUID)];
|
||||
id_vector identifier1(make_vector());
|
||||
id_vector identifier2(make_vector());
|
||||
EXPECT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[i], true, i,
|
||||
identifier1));
|
||||
FileID fileid(exe_name);
|
||||
EXPECT_TRUE(fileid.ElfFileIdentifier(identifier2));
|
||||
char identifier_string1[37];
|
||||
char identifier_string2[37];
|
||||
FileID::ConvertIdentifierToString(identifier1, identifier_string1,
|
||||
37);
|
||||
FileID::ConvertIdentifierToString(identifier2, identifier_string2,
|
||||
37);
|
||||
EXPECT_STREQ(identifier_string1, identifier_string2);
|
||||
|
||||
string identifier_string1 =
|
||||
FileID::ConvertIdentifierToUUIDString(identifier1);
|
||||
string identifier_string2 =
|
||||
FileID::ConvertIdentifierToUUIDString(identifier2);
|
||||
EXPECT_EQ(identifier_string1, identifier_string2);
|
||||
}
|
||||
|
||||
/* Get back to normal behavior of TEST*() macros wrt TestBody. */
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
|
||||
#include "client/linux/minidump_writer/proc_cpuinfo_reader.h"
|
||||
#include "client/minidump_file_writer.h"
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/minidump_type_helper.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
@ -81,8 +82,10 @@
|
||||
namespace {
|
||||
|
||||
using google_breakpad::AppMemoryList;
|
||||
using google_breakpad::auto_wasteful_vector;
|
||||
using google_breakpad::ExceptionHandler;
|
||||
using google_breakpad::CpuSet;
|
||||
using google_breakpad::kDefaultBuildIdSize;
|
||||
using google_breakpad::LineReader;
|
||||
using google_breakpad::LinuxDumper;
|
||||
using google_breakpad::LinuxPtraceDumper;
|
||||
@ -272,6 +275,14 @@ class MinidumpWriter {
|
||||
if (max_stack_len >= 0 &&
|
||||
stack_len > static_cast<unsigned int>(max_stack_len)) {
|
||||
stack_len = max_stack_len;
|
||||
// Skip empty chunks of length max_stack_len.
|
||||
uintptr_t int_stack = reinterpret_cast<uintptr_t>(stack);
|
||||
if (max_stack_len > 0) {
|
||||
while (int_stack + max_stack_len < stack_pointer) {
|
||||
int_stack += max_stack_len;
|
||||
}
|
||||
}
|
||||
stack = reinterpret_cast<const void*>(int_stack);
|
||||
}
|
||||
if (!memory.Allocate(stack_len))
|
||||
return false;
|
||||
@ -546,41 +557,40 @@ class MinidumpWriter {
|
||||
mod->base_of_image = mapping.start_addr;
|
||||
mod->size_of_image = mapping.size;
|
||||
|
||||
uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX];
|
||||
uint8_t* cv_ptr = cv_buf;
|
||||
auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
|
||||
dumper_->allocator());
|
||||
|
||||
const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
|
||||
my_memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
|
||||
cv_ptr += sizeof(cv_signature);
|
||||
uint8_t* signature = cv_ptr;
|
||||
cv_ptr += sizeof(MDGUID);
|
||||
if (identifier) {
|
||||
// GUID was provided by caller.
|
||||
my_memcpy(signature, identifier, sizeof(MDGUID));
|
||||
identifier_bytes.insert(identifier_bytes.end(),
|
||||
identifier,
|
||||
identifier + sizeof(MDGUID));
|
||||
} else {
|
||||
// Note: ElfFileIdentifierForMapping() can manipulate the |mapping.name|.
|
||||
dumper_->ElfFileIdentifierForMapping(mapping, member,
|
||||
mapping_id, signature);
|
||||
dumper_->ElfFileIdentifierForMapping(mapping,
|
||||
member,
|
||||
mapping_id,
|
||||
identifier_bytes);
|
||||
}
|
||||
|
||||
if (!identifier_bytes.empty()) {
|
||||
UntypedMDRVA cv(&minidump_writer_);
|
||||
if (!cv.Allocate(MDCVInfoELF_minsize + identifier_bytes.size()))
|
||||
return false;
|
||||
|
||||
const uint32_t cv_signature = MD_CVINFOELF_SIGNATURE;
|
||||
cv.Copy(&cv_signature, sizeof(cv_signature));
|
||||
cv.Copy(cv.position() + sizeof(cv_signature), &identifier_bytes[0],
|
||||
identifier_bytes.size());
|
||||
|
||||
mod->cv_record = cv.location();
|
||||
}
|
||||
my_memset(cv_ptr, 0, sizeof(uint32_t)); // Set age to 0 on Linux.
|
||||
cv_ptr += sizeof(uint32_t);
|
||||
|
||||
char file_name[NAME_MAX];
|
||||
char file_path[NAME_MAX];
|
||||
LinuxDumper::GetMappingEffectiveNameAndPath(
|
||||
dumper_->GetMappingEffectiveNameAndPath(
|
||||
mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
|
||||
|
||||
const size_t file_name_len = my_strlen(file_name);
|
||||
UntypedMDRVA cv(&minidump_writer_);
|
||||
if (!cv.Allocate(MDCVInfoPDB70_minsize + file_name_len + 1))
|
||||
return false;
|
||||
|
||||
// Write pdb_file_name
|
||||
my_memcpy(cv_ptr, file_name, file_name_len + 1);
|
||||
cv.Copy(cv_buf, MDCVInfoPDB70_minsize + file_name_len + 1);
|
||||
|
||||
mod->cv_record = cv.location();
|
||||
|
||||
MDLocationDescriptor ld;
|
||||
if (!minidump_writer_.WriteString(file_path, my_strlen(file_path), &ld))
|
||||
return false;
|
||||
|
@ -54,10 +54,6 @@
|
||||
|
||||
using namespace google_breakpad;
|
||||
|
||||
// Length of a formatted GUID string =
|
||||
// sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator)
|
||||
const int kGUIDStringSize = 37;
|
||||
|
||||
namespace {
|
||||
|
||||
typedef testing::Test MinidumpWriterTest;
|
||||
@ -137,19 +133,7 @@ TEST(MinidumpWriterTest, MappingInfo) {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||
};
|
||||
char module_identifier_buffer[kGUIDStringSize];
|
||||
FileID::ConvertIdentifierToString(kModuleGUID,
|
||||
module_identifier_buffer,
|
||||
sizeof(module_identifier_buffer));
|
||||
string module_identifier(module_identifier_buffer);
|
||||
// Strip out dashes
|
||||
size_t pos;
|
||||
while ((pos = module_identifier.find('-')) != string::npos) {
|
||||
module_identifier.erase(pos, 1);
|
||||
}
|
||||
// And append a zero, because module IDs include an "age" field
|
||||
// which is always zero on Linux.
|
||||
module_identifier += "0";
|
||||
const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
|
||||
|
||||
// Get some memory.
|
||||
char* memory =
|
||||
@ -230,6 +214,53 @@ TEST(MinidumpWriterTest, MappingInfo) {
|
||||
close(fds[1]);
|
||||
}
|
||||
|
||||
// Test that a binary with a longer-than-usual build id note
|
||||
// makes its way all the way through to the minidump unscathed.
|
||||
// The linux_client_unittest is linked with an explicit --build-id
|
||||
// in Makefile.am.
|
||||
TEST(MinidumpWriterTest, BuildIDLong) {
|
||||
int fds[2];
|
||||
ASSERT_NE(-1, pipe(fds));
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
close(fds[1]);
|
||||
char b;
|
||||
IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
|
||||
close(fds[0]);
|
||||
syscall(__NR_exit);
|
||||
}
|
||||
close(fds[0]);
|
||||
|
||||
ExceptionHandler::CrashContext context;
|
||||
memset(&context, 0, sizeof(context));
|
||||
ASSERT_EQ(0, getcontext(&context.context));
|
||||
context.tid = child;
|
||||
|
||||
AutoTempDir temp_dir;
|
||||
const string dump_path = temp_dir.path() + kMDWriterUnitTestFileName;
|
||||
|
||||
EXPECT_TRUE(WriteMinidump(dump_path.c_str(),
|
||||
child, &context, sizeof(context)));
|
||||
close(fds[1]);
|
||||
|
||||
// Read the minidump. Load the module list, and ensure that
|
||||
// the main module has the correct debug id and code id.
|
||||
Minidump minidump(dump_path);
|
||||
ASSERT_TRUE(minidump.Read());
|
||||
|
||||
MinidumpModuleList* module_list = minidump.GetModuleList();
|
||||
ASSERT_TRUE(module_list);
|
||||
const MinidumpModule* module = module_list->GetMainModule();
|
||||
ASSERT_TRUE(module);
|
||||
const string module_identifier = "030201000504070608090A0B0C0D0E0F0";
|
||||
// This is passed explicitly to the linker in Makefile.am
|
||||
const string build_id =
|
||||
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
|
||||
EXPECT_EQ(module_identifier, module->debug_identifier());
|
||||
EXPECT_EQ(build_id, module->code_identifier());
|
||||
}
|
||||
|
||||
// Test that mapping info can be specified, and that it overrides
|
||||
// existing mappings that are wholly contained within the specified
|
||||
// range.
|
||||
@ -245,19 +276,7 @@ TEST(MinidumpWriterTest, MappingInfoContained) {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||
};
|
||||
char module_identifier_buffer[kGUIDStringSize];
|
||||
FileID::ConvertIdentifierToString(kModuleGUID,
|
||||
module_identifier_buffer,
|
||||
sizeof(module_identifier_buffer));
|
||||
string module_identifier(module_identifier_buffer);
|
||||
// Strip out dashes
|
||||
size_t pos;
|
||||
while ((pos = module_identifier.find('-')) != string::npos) {
|
||||
module_identifier.erase(pos, 1);
|
||||
}
|
||||
// And append a zero, because module IDs include an "age" field
|
||||
// which is always zero on Linux.
|
||||
module_identifier += "0";
|
||||
const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
|
||||
|
||||
// mmap a file
|
||||
AutoTempDir temp_dir;
|
||||
@ -410,12 +429,10 @@ TEST(MinidumpWriterTest, DeletedBinary) {
|
||||
EXPECT_STREQ(binpath.c_str(), module->code_file().c_str());
|
||||
// Check that the file ID is correct.
|
||||
FileID fileid(helper_path.c_str());
|
||||
uint8_t identifier[sizeof(MDGUID)];
|
||||
PageAllocator allocator;
|
||||
wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
|
||||
EXPECT_TRUE(fileid.ElfFileIdentifier(identifier));
|
||||
char identifier_string[kGUIDStringSize];
|
||||
FileID::ConvertIdentifierToString(identifier,
|
||||
identifier_string,
|
||||
kGUIDStringSize);
|
||||
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
|
||||
string module_identifier(identifier_string);
|
||||
// Strip out dashes
|
||||
size_t pos;
|
||||
|
@ -583,7 +583,6 @@
|
||||
4DBE4769134A4F080072546A /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
||||
8B31007011F0CD3C00FCF3E4 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = ../../common/mac/GTMDefines.h; sourceTree = SOURCE_ROOT; };
|
||||
8B3101E911F0CDE300FCF3E4 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
8B31022211F0CE1000FCF3E4 /* GTMGarbageCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMGarbageCollection.h; path = ../../common/mac/GTMGarbageCollection.h; sourceTree = SOURCE_ROOT; };
|
||||
8B31027711F0D3AF00FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B31027811F0D3AF00FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B31FFF611F0C90500FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
@ -955,7 +954,6 @@
|
||||
children = (
|
||||
162F64F0161C577500CD68D5 /* arch_utilities.cc */,
|
||||
162F64F1161C577500CD68D5 /* arch_utilities.h */,
|
||||
8B31022211F0CE1000FCF3E4 /* GTMGarbageCollection.h */,
|
||||
8B31007011F0CD3C00FCF3E4 /* GTMDefines.h */,
|
||||
F9C77E0F0F7DDF650045F7DB /* testing */,
|
||||
F9C44EE70EF0A3C1003AEBAA /* GTMLogger.h */,
|
||||
|
@ -75,6 +75,8 @@
|
||||
'dwarf/dwarf2reader.cc',
|
||||
'dwarf/dwarf2reader.h',
|
||||
'dwarf/dwarf2reader_test_common.h',
|
||||
'dwarf/elf_reader.cc',
|
||||
'dwarf/elf_reader.h',
|
||||
'dwarf/functioninfo.cc',
|
||||
'dwarf/functioninfo.h',
|
||||
'dwarf/line_state_machine.h',
|
||||
|
@ -243,4 +243,8 @@ uint64 ByteReader::ReadEncodedPointer(const uint8_t *buffer,
|
||||
return pointer;
|
||||
}
|
||||
|
||||
Endianness ByteReader::GetEndianness() const {
|
||||
return endian_;
|
||||
}
|
||||
|
||||
} // namespace dwarf2reader
|
||||
|
@ -280,6 +280,7 @@ class ByteReader {
|
||||
DwarfPointerEncoding encoding,
|
||||
size_t *len) const;
|
||||
|
||||
Endianness GetEndianness() const;
|
||||
private:
|
||||
|
||||
// Function pointer type for our address and offset readers.
|
||||
|
@ -149,7 +149,10 @@ enum DwarfForm {
|
||||
DW_FORM_sec_offset = 0x17,
|
||||
DW_FORM_exprloc = 0x18,
|
||||
DW_FORM_flag_present = 0x19,
|
||||
DW_FORM_ref_sig8 = 0x20
|
||||
DW_FORM_ref_sig8 = 0x20,
|
||||
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
|
||||
DW_FORM_GNU_addr_index = 0x1f01,
|
||||
DW_FORM_GNU_str_index = 0x1f02
|
||||
};
|
||||
|
||||
// Attribute names and codes
|
||||
@ -264,6 +267,13 @@ enum DwarfAttribute {
|
||||
DW_AT_body_begin = 0x2105,
|
||||
DW_AT_body_end = 0x2106,
|
||||
DW_AT_GNU_vector = 0x2107,
|
||||
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
|
||||
DW_AT_GNU_dwo_name = 0x2130,
|
||||
DW_AT_GNU_dwo_id = 0x2131,
|
||||
DW_AT_GNU_ranges_base = 0x2132,
|
||||
DW_AT_GNU_addr_base = 0x2133,
|
||||
DW_AT_GNU_pubnames = 0x2134,
|
||||
DW_AT_GNU_pubtypes = 0x2135,
|
||||
// VMS extensions.
|
||||
DW_AT_VMS_rtnbeg_pd_address = 0x2201,
|
||||
// UPC extension.
|
||||
@ -491,7 +501,22 @@ enum DwarfOpcode {
|
||||
DW_OP_lo_user =0xe0,
|
||||
DW_OP_hi_user =0xff,
|
||||
// GNU extensions
|
||||
DW_OP_GNU_push_tls_address =0xe0
|
||||
DW_OP_GNU_push_tls_address =0xe0,
|
||||
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
|
||||
DW_OP_GNU_addr_index =0xfb,
|
||||
DW_OP_GNU_const_index =0xfc
|
||||
};
|
||||
|
||||
// Section identifiers for DWP files
|
||||
enum DwarfSectionId {
|
||||
DW_SECT_INFO = 1,
|
||||
DW_SECT_TYPES = 2,
|
||||
DW_SECT_ABBREV = 3,
|
||||
DW_SECT_LINE = 4,
|
||||
DW_SECT_LOC = 5,
|
||||
DW_SECT_STR_OFFSETS = 6,
|
||||
DW_SECT_MACINFO = 7,
|
||||
DW_SECT_MACRO = 8
|
||||
};
|
||||
|
||||
// Source languages. These are values for DW_AT_language.
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "common/dwarf/bytereader-inl.h"
|
||||
#include "common/dwarf/bytereader.h"
|
||||
#include "common/dwarf/line_state_machine.h"
|
||||
@ -51,11 +53,38 @@
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset,
|
||||
CompilationUnit::CompilationUnit(const string& path,
|
||||
const SectionMap& sections, uint64 offset,
|
||||
ByteReader* reader, Dwarf2Handler* handler)
|
||||
: offset_from_section_start_(offset), reader_(reader),
|
||||
sections_(sections), handler_(handler), abbrevs_(NULL),
|
||||
string_buffer_(NULL), string_buffer_length_(0) {}
|
||||
: path_(path), offset_from_section_start_(offset), reader_(reader),
|
||||
sections_(sections), handler_(handler), abbrevs_(),
|
||||
string_buffer_(NULL), string_buffer_length_(0),
|
||||
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
|
||||
addr_buffer_(NULL), addr_buffer_length_(0),
|
||||
is_split_dwarf_(false), dwo_id_(0), dwo_name_(),
|
||||
skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0),
|
||||
have_checked_for_dwp_(false), dwp_path_(),
|
||||
dwp_byte_reader_(), dwp_reader_() {}
|
||||
|
||||
// Initialize a compilation unit from a .dwo or .dwp file.
|
||||
// In this case, we need the .debug_addr section from the
|
||||
// executable file that contains the corresponding skeleton
|
||||
// compilation unit. We also inherit the Dwarf2Handler from
|
||||
// the executable file, and call it as if we were still
|
||||
// processing the original compilation unit.
|
||||
|
||||
void CompilationUnit::SetSplitDwarf(const uint8_t* addr_buffer,
|
||||
uint64 addr_buffer_length,
|
||||
uint64 addr_base,
|
||||
uint64 ranges_base,
|
||||
uint64 dwo_id) {
|
||||
is_split_dwarf_ = true;
|
||||
addr_buffer_ = addr_buffer;
|
||||
addr_buffer_length_ = addr_buffer_length;
|
||||
addr_base_ = addr_base;
|
||||
ranges_base_ = ranges_base;
|
||||
skeleton_dwo_id_ = dwo_id;
|
||||
}
|
||||
|
||||
// Read a DWARF2/3 abbreviation section.
|
||||
// Each abbrev consists of a abbreviation number, a tag, a byte
|
||||
@ -174,6 +203,8 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
|
||||
return start + strlen(reinterpret_cast<const char *>(start)) + 1;
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
case DW_FORM_GNU_str_index:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
reader_->ReadUnsignedLEB128(start, &len);
|
||||
return start + len;
|
||||
|
||||
@ -235,7 +266,9 @@ void CompilationUnit::ReadHeader() {
|
||||
header_.abbrev_offset = reader_->ReadOffset(headerptr);
|
||||
headerptr += reader_->OffsetSize();
|
||||
|
||||
assert(headerptr + 1 < buffer_ + buffer_length_);
|
||||
// Compare against less than or equal because this may be the last
|
||||
// section in the file.
|
||||
assert(headerptr + 1 <= buffer_ + buffer_length_);
|
||||
header_.address_size = reader_->ReadOneByte(headerptr);
|
||||
reader_->SetAddressSize(header_.address_size);
|
||||
headerptr += 1;
|
||||
@ -296,9 +329,31 @@ uint64 CompilationUnit::Start() {
|
||||
string_buffer_length_ = iter->second.second;
|
||||
}
|
||||
|
||||
// Set the string offsets section if we have one.
|
||||
iter = sections_.find(".debug_str_offsets");
|
||||
if (iter != sections_.end()) {
|
||||
str_offsets_buffer_ = iter->second.first;
|
||||
str_offsets_buffer_length_ = iter->second.second;
|
||||
}
|
||||
|
||||
// Set the address section if we have one.
|
||||
iter = sections_.find(".debug_addr");
|
||||
if (iter != sections_.end()) {
|
||||
addr_buffer_ = iter->second.first;
|
||||
addr_buffer_length_ = iter->second.second;
|
||||
}
|
||||
|
||||
// Now that we have our abbreviations, start processing DIE's.
|
||||
ProcessDIEs();
|
||||
|
||||
// If this is a skeleton compilation unit generated with split DWARF,
|
||||
// and the client needs the full debug info, we need to find the full
|
||||
// compilation unit in a .dwo or .dwp file.
|
||||
if (!is_split_dwarf_
|
||||
&& dwo_name_ != NULL
|
||||
&& handler_->NeedSplitDebugInfo())
|
||||
ProcessSplitDwarf();
|
||||
|
||||
return ourlength;
|
||||
}
|
||||
|
||||
@ -320,48 +375,46 @@ const uint8_t *CompilationUnit::ProcessAttribute(
|
||||
return ProcessAttribute(dieoffset, start, attr, form);
|
||||
|
||||
case DW_FORM_flag_present:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form, 1);
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form, 1);
|
||||
return start;
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_flag:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadOneByte(start));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadOneByte(start));
|
||||
return start + 1;
|
||||
case DW_FORM_data2:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadTwoBytes(start));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadTwoBytes(start));
|
||||
return start + 2;
|
||||
case DW_FORM_data4:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadFourBytes(start));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadFourBytes(start));
|
||||
return start + 4;
|
||||
case DW_FORM_data8:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadEightBytes(start));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadEightBytes(start));
|
||||
return start + 8;
|
||||
case DW_FORM_string: {
|
||||
const char *str = reinterpret_cast<const char *>(start);
|
||||
handler_->ProcessAttributeString(dieoffset, attr, form,
|
||||
str);
|
||||
ProcessAttributeString(dieoffset, attr, form, str);
|
||||
return start + strlen(str) + 1;
|
||||
}
|
||||
case DW_FORM_udata:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadUnsignedLEB128(start,
|
||||
&len));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadUnsignedLEB128(start, &len));
|
||||
return start + len;
|
||||
|
||||
case DW_FORM_sdata:
|
||||
handler_->ProcessAttributeSigned(dieoffset, attr, form,
|
||||
reader_->ReadSignedLEB128(start, &len));
|
||||
ProcessAttributeSigned(dieoffset, attr, form,
|
||||
reader_->ReadSignedLEB128(start, &len));
|
||||
return start + len;
|
||||
case DW_FORM_addr:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadAddress(start));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadAddress(start));
|
||||
return start + reader_->AddressSize();
|
||||
case DW_FORM_sec_offset:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadOffset(start));
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadOffset(start));
|
||||
return start + reader_->OffsetSize();
|
||||
|
||||
case DW_FORM_ref1:
|
||||
@ -441,10 +494,32 @@ const uint8_t *CompilationUnit::ProcessAttribute(
|
||||
assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_);
|
||||
|
||||
const char *str = reinterpret_cast<const char *>(string_buffer_ + offset);
|
||||
handler_->ProcessAttributeString(dieoffset, attr, form,
|
||||
str);
|
||||
ProcessAttributeString(dieoffset, attr, form, str);
|
||||
return start + reader_->OffsetSize();
|
||||
}
|
||||
|
||||
case DW_FORM_GNU_str_index: {
|
||||
uint64 str_index = reader_->ReadUnsignedLEB128(start, &len);
|
||||
const uint8_t* offset_ptr =
|
||||
str_offsets_buffer_ + str_index * reader_->OffsetSize();
|
||||
const uint64 offset = reader_->ReadOffset(offset_ptr);
|
||||
if (offset >= string_buffer_length_) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* str = reinterpret_cast<const char *>(string_buffer_) + offset;
|
||||
ProcessAttributeString(dieoffset, attr, form, str);
|
||||
return start + len;
|
||||
break;
|
||||
}
|
||||
case DW_FORM_GNU_addr_index: {
|
||||
uint64 addr_index = reader_->ReadUnsignedLEB128(start, &len);
|
||||
const uint8_t* addr_ptr =
|
||||
addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadAddress(addr_ptr));
|
||||
return start + len;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Unhandled form type\n");
|
||||
return NULL;
|
||||
@ -458,6 +533,16 @@ const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset,
|
||||
i++) {
|
||||
start = ProcessAttribute(dieoffset, start, i->first, i->second);
|
||||
}
|
||||
|
||||
// If this is a compilation unit in a split DWARF object, verify that
|
||||
// the dwo_id matches. If it does not match, we will ignore this
|
||||
// compilation unit.
|
||||
if (abbrev.tag == DW_TAG_compile_unit
|
||||
&& is_split_dwarf_
|
||||
&& dwo_id_ != skeleton_dwo_id_) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
@ -515,6 +600,307 @@ void CompilationUnit::ProcessDIEs() {
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a valid ELF file and return the Address size.
|
||||
// Returns 0 if not a valid ELF file.
|
||||
inline int GetElfWidth(const ElfReader& elf) {
|
||||
if (elf.IsElf32File())
|
||||
return 4;
|
||||
if (elf.IsElf64File())
|
||||
return 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CompilationUnit::ProcessSplitDwarf() {
|
||||
struct stat statbuf;
|
||||
if (!have_checked_for_dwp_) {
|
||||
// Look for a .dwp file in the same directory as the executable.
|
||||
have_checked_for_dwp_ = true;
|
||||
string dwp_suffix(".dwp");
|
||||
dwp_path_ = path_ + dwp_suffix;
|
||||
if (stat(dwp_path_.c_str(), &statbuf) != 0) {
|
||||
// Fall back to a split .debug file in the same directory.
|
||||
string debug_suffix(".debug");
|
||||
dwp_path_ = path_;
|
||||
size_t found = path_.rfind(debug_suffix);
|
||||
if (found + debug_suffix.length() == path_.length())
|
||||
dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix);
|
||||
}
|
||||
if (stat(dwp_path_.c_str(), &statbuf) == 0) {
|
||||
ElfReader* elf = new ElfReader(dwp_path_);
|
||||
int width = GetElfWidth(*elf);
|
||||
if (width != 0) {
|
||||
dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness()));
|
||||
dwp_byte_reader_->SetAddressSize(width);
|
||||
dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf));
|
||||
dwp_reader_->Initialize();
|
||||
} else {
|
||||
delete elf;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool found_in_dwp = false;
|
||||
if (dwp_reader_) {
|
||||
// If we have a .dwp file, read the debug sections for the requested CU.
|
||||
SectionMap sections;
|
||||
dwp_reader_->ReadDebugSectionsForCU(dwo_id_, §ions);
|
||||
if (!sections.empty()) {
|
||||
found_in_dwp = true;
|
||||
CompilationUnit dwp_comp_unit(dwp_path_, sections, 0,
|
||||
dwp_byte_reader_.get(), handler_);
|
||||
dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_,
|
||||
ranges_base_, dwo_id_);
|
||||
dwp_comp_unit.Start();
|
||||
}
|
||||
}
|
||||
if (!found_in_dwp) {
|
||||
// If no .dwp file, try to open the .dwo file.
|
||||
if (stat(dwo_name_, &statbuf) == 0) {
|
||||
ElfReader elf(dwo_name_);
|
||||
int width = GetElfWidth(elf);
|
||||
if (width != 0) {
|
||||
ByteReader reader(ENDIANNESS_LITTLE);
|
||||
reader.SetAddressSize(width);
|
||||
SectionMap sections;
|
||||
ReadDebugSectionsFromDwo(&elf, §ions);
|
||||
CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader,
|
||||
handler_);
|
||||
dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_,
|
||||
addr_base_, ranges_base_, dwo_id_);
|
||||
dwo_comp_unit.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader,
|
||||
SectionMap* sections) {
|
||||
static const char* const section_names[] = {
|
||||
".debug_abbrev",
|
||||
".debug_info",
|
||||
".debug_str_offsets",
|
||||
".debug_str"
|
||||
};
|
||||
for (unsigned int i = 0u;
|
||||
i < sizeof(section_names)/sizeof(*(section_names)); ++i) {
|
||||
string base_name = section_names[i];
|
||||
string dwo_name = base_name + ".dwo";
|
||||
size_t section_size;
|
||||
const char* section_data = elf_reader->GetSectionByName(dwo_name,
|
||||
§ion_size);
|
||||
if (section_data != NULL)
|
||||
sections->insert(std::make_pair(
|
||||
base_name, std::make_pair(
|
||||
reinterpret_cast<const uint8_t *>(section_data),
|
||||
section_size)));
|
||||
}
|
||||
}
|
||||
|
||||
DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader)
|
||||
: elf_reader_(elf_reader), byte_reader_(byte_reader),
|
||||
cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL),
|
||||
string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0),
|
||||
nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL),
|
||||
offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL),
|
||||
abbrev_size_(0), info_data_(NULL), info_size_(0),
|
||||
str_offsets_data_(NULL), str_offsets_size_(0) {}
|
||||
|
||||
DwpReader::~DwpReader() {
|
||||
if (elf_reader_) delete elf_reader_;
|
||||
}
|
||||
|
||||
void DwpReader::Initialize() {
|
||||
cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index",
|
||||
&cu_index_size_);
|
||||
if (cu_index_ == NULL) {
|
||||
return;
|
||||
}
|
||||
// The .debug_str.dwo section is shared by all CUs in the file.
|
||||
string_buffer_ = elf_reader_->GetSectionByName(".debug_str.dwo",
|
||||
&string_buffer_size_);
|
||||
|
||||
version_ = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(cu_index_));
|
||||
|
||||
if (version_ == 1) {
|
||||
nslots_ = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(cu_index_)
|
||||
+ 3 * sizeof(uint32));
|
||||
phash_ = cu_index_ + 4 * sizeof(uint32);
|
||||
pindex_ = phash_ + nslots_ * sizeof(uint64);
|
||||
shndx_pool_ = pindex_ + nslots_ * sizeof(uint32);
|
||||
if (shndx_pool_ >= cu_index_ + cu_index_size_) {
|
||||
version_ = 0;
|
||||
}
|
||||
} else if (version_ == 2) {
|
||||
ncolumns_ = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(cu_index_) + sizeof(uint32));
|
||||
nunits_ = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(cu_index_) + 2 * sizeof(uint32));
|
||||
nslots_ = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(cu_index_) + 3 * sizeof(uint32));
|
||||
phash_ = cu_index_ + 4 * sizeof(uint32);
|
||||
pindex_ = phash_ + nslots_ * sizeof(uint64);
|
||||
offset_table_ = pindex_ + nslots_ * sizeof(uint32);
|
||||
size_table_ = offset_table_ + ncolumns_ * (nunits_ + 1) * sizeof(uint32);
|
||||
abbrev_data_ = elf_reader_->GetSectionByName(".debug_abbrev.dwo",
|
||||
&abbrev_size_);
|
||||
info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_);
|
||||
str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo",
|
||||
&str_offsets_size_);
|
||||
if (size_table_ >= cu_index_ + cu_index_size_) {
|
||||
version_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DwpReader::ReadDebugSectionsForCU(uint64 dwo_id,
|
||||
SectionMap* sections) {
|
||||
if (version_ == 1) {
|
||||
int slot = LookupCU(dwo_id);
|
||||
if (slot == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The index table points to the section index pool, where we
|
||||
// can read a list of section indexes for the debug sections
|
||||
// for the CU whose dwo_id we are looking for.
|
||||
int index = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(pindex_)
|
||||
+ slot * sizeof(uint32));
|
||||
const char* shndx_list = shndx_pool_ + index * sizeof(uint32);
|
||||
for (;;) {
|
||||
if (shndx_list >= cu_index_ + cu_index_size_) {
|
||||
version_ = 0;
|
||||
return;
|
||||
}
|
||||
unsigned int shndx = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(shndx_list));
|
||||
shndx_list += sizeof(uint32);
|
||||
if (shndx == 0)
|
||||
break;
|
||||
const char* section_name = elf_reader_->GetSectionName(shndx);
|
||||
size_t section_size;
|
||||
const char* section_data;
|
||||
// We're only interested in these four debug sections.
|
||||
// The section names in the .dwo file end with ".dwo", but we
|
||||
// add them to the sections table with their normal names.
|
||||
if (!strncmp(section_name, ".debug_abbrev", strlen(".debug_abbrev"))) {
|
||||
section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size);
|
||||
sections->insert(std::make_pair(
|
||||
".debug_abbrev",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
|
||||
section_size)));
|
||||
} else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) {
|
||||
section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size);
|
||||
sections->insert(std::make_pair(
|
||||
".debug_info",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
|
||||
section_size)));
|
||||
} else if (!strncmp(section_name, ".debug_str_offsets",
|
||||
strlen(".debug_str_offsets"))) {
|
||||
section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size);
|
||||
sections->insert(std::make_pair(
|
||||
".debug_str_offsets",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
|
||||
section_size)));
|
||||
}
|
||||
}
|
||||
sections->insert(std::make_pair(
|
||||
".debug_str",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
|
||||
string_buffer_size_)));
|
||||
} else if (version_ == 2) {
|
||||
uint32 index = LookupCUv2(dwo_id);
|
||||
if (index == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The index points to a row in each of the section offsets table
|
||||
// and the section size table, where we can read the offsets and sizes
|
||||
// of the contributions to each debug section from the CU whose dwo_id
|
||||
// we are looking for. Row 0 of the section offsets table has the
|
||||
// section ids for each column of the table. The size table begins
|
||||
// with row 1.
|
||||
const char* id_row = offset_table_;
|
||||
const char* offset_row = offset_table_
|
||||
+ index * ncolumns_ * sizeof(uint32);
|
||||
const char* size_row =
|
||||
size_table_ + (index - 1) * ncolumns_ * sizeof(uint32);
|
||||
if (size_row + ncolumns_ * sizeof(uint32) > cu_index_ + cu_index_size_) {
|
||||
version_ = 0;
|
||||
return;
|
||||
}
|
||||
for (unsigned int col = 0u; col < ncolumns_; ++col) {
|
||||
uint32 section_id =
|
||||
byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row)
|
||||
+ col * sizeof(uint32));
|
||||
uint32 offset = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(offset_row)
|
||||
+ col * sizeof(uint32));
|
||||
uint32 size = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(size_row) + col * sizeof(uint32));
|
||||
if (section_id == DW_SECT_ABBREV) {
|
||||
sections->insert(std::make_pair(
|
||||
".debug_abbrev",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (abbrev_data_)
|
||||
+ offset, size)));
|
||||
} else if (section_id == DW_SECT_INFO) {
|
||||
sections->insert(std::make_pair(
|
||||
".debug_info",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (info_data_)
|
||||
+ offset, size)));
|
||||
} else if (section_id == DW_SECT_STR_OFFSETS) {
|
||||
sections->insert(std::make_pair(
|
||||
".debug_str_offsets",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (str_offsets_data_)
|
||||
+ offset, size)));
|
||||
}
|
||||
}
|
||||
sections->insert(std::make_pair(
|
||||
".debug_str",
|
||||
std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
|
||||
string_buffer_size_)));
|
||||
}
|
||||
}
|
||||
|
||||
int DwpReader::LookupCU(uint64 dwo_id) {
|
||||
uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
|
||||
uint64 probe = byte_reader_.ReadEightBytes(
|
||||
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
|
||||
if (probe != 0 && probe != dwo_id) {
|
||||
uint32 secondary_hash =
|
||||
(static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
|
||||
do {
|
||||
slot = (slot + secondary_hash) & (nslots_ - 1);
|
||||
probe = byte_reader_.ReadEightBytes(
|
||||
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
|
||||
} while (probe != 0 && probe != dwo_id);
|
||||
}
|
||||
if (probe == 0)
|
||||
return -1;
|
||||
return slot;
|
||||
}
|
||||
|
||||
uint32 DwpReader::LookupCUv2(uint64 dwo_id) {
|
||||
uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
|
||||
uint64 probe = byte_reader_.ReadEightBytes(
|
||||
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
|
||||
uint32 index = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
|
||||
if (index != 0 && probe != dwo_id) {
|
||||
uint32 secondary_hash =
|
||||
(static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
|
||||
do {
|
||||
slot = (slot + secondary_hash) & (nslots_ - 1);
|
||||
probe = byte_reader_.ReadEightBytes(
|
||||
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
|
||||
index = byte_reader_.ReadFourBytes(
|
||||
reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
|
||||
} while (index != 0 && probe != dwo_id);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length,
|
||||
ByteReader* reader, LineInfoHandler* handler):
|
||||
handler_(handler), reader_(reader), buffer_(buffer) {
|
||||
|
@ -47,16 +47,19 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "common/dwarf/bytereader.h"
|
||||
#include "common/dwarf/dwarf2enums.h"
|
||||
#include "common/dwarf/types.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "common/dwarf/elf_reader.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
struct LineStateMachine;
|
||||
class Dwarf2Handler;
|
||||
class LineInfoHandler;
|
||||
class DwpReader;
|
||||
|
||||
// This maps from a string naming a section to a pair containing a
|
||||
// the data for the section, and the size of the section.
|
||||
@ -184,151 +187,10 @@ class LineInfoHandler {
|
||||
uint32 file_num, uint32 line_num, uint32 column_num) { }
|
||||
};
|
||||
|
||||
// The base of DWARF2/3 debug info is a DIE (Debugging Information
|
||||
// Entry.
|
||||
// DWARF groups DIE's into a tree and calls the root of this tree a
|
||||
// "compilation unit". Most of the time, there is one compilation
|
||||
// unit in the .debug_info section for each file that had debug info
|
||||
// generated.
|
||||
// Each DIE consists of
|
||||
|
||||
// 1. a tag specifying a thing that is being described (ie
|
||||
// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
|
||||
// 2. attributes (such as DW_AT_location for location in memory,
|
||||
// DW_AT_name for name), and data for each attribute.
|
||||
// 3. A flag saying whether the DIE has children or not
|
||||
|
||||
// In order to gain some amount of compression, the format of
|
||||
// each DIE (tag name, attributes and data forms for the attributes)
|
||||
// are stored in a separate table called the "abbreviation table".
|
||||
// This is done because a large number of DIEs have the exact same tag
|
||||
// and list of attributes, but different data for those attributes.
|
||||
// As a result, the .debug_info section is just a stream of data, and
|
||||
// requires reading of the .debug_abbrev section to say what the data
|
||||
// means.
|
||||
|
||||
// As a warning to the user, it should be noted that the reason for
|
||||
// using absolute offsets from the beginning of .debug_info is that
|
||||
// DWARF2/3 supports referencing DIE's from other DIE's by their offset
|
||||
// from either the current compilation unit start, *or* the beginning
|
||||
// of the .debug_info section. This means it is possible to reference
|
||||
// a DIE in one compilation unit from a DIE in another compilation
|
||||
// unit. This style of reference is usually used to eliminate
|
||||
// duplicated information that occurs across compilation
|
||||
// units, such as base types, etc. GCC 3.4+ support this with
|
||||
// -feliminate-dwarf2-dups. Other toolchains will sometimes do
|
||||
// duplicate elimination in the linker.
|
||||
|
||||
class CompilationUnit {
|
||||
public:
|
||||
|
||||
// Initialize a compilation unit. This requires a map of sections,
|
||||
// the offset of this compilation unit in the .debug_info section, a
|
||||
// ByteReader, and a Dwarf2Handler class to call callbacks in.
|
||||
CompilationUnit(const SectionMap& sections, uint64 offset,
|
||||
ByteReader* reader, Dwarf2Handler* handler);
|
||||
virtual ~CompilationUnit() {
|
||||
if (abbrevs_) delete abbrevs_;
|
||||
}
|
||||
|
||||
// Begin reading a Dwarf2 compilation unit, and calling the
|
||||
// callbacks in the Dwarf2Handler
|
||||
|
||||
// Return the full length of the compilation unit, including
|
||||
// headers. This plus the starting offset passed to the constructor
|
||||
// is the offset of the end of the compilation unit --- and the
|
||||
// start of the next compilation unit, if there is one.
|
||||
uint64 Start();
|
||||
|
||||
private:
|
||||
|
||||
// This struct represents a single DWARF2/3 abbreviation
|
||||
// The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
|
||||
// tag and a list of attributes, as well as the data form of each attribute.
|
||||
struct Abbrev {
|
||||
uint64 number;
|
||||
enum DwarfTag tag;
|
||||
bool has_children;
|
||||
AttributeList attributes;
|
||||
};
|
||||
|
||||
// A DWARF2/3 compilation unit header. This is not the same size as
|
||||
// in the actual file, as the one in the file may have a 32 bit or
|
||||
// 64 bit length.
|
||||
struct CompilationUnitHeader {
|
||||
uint64 length;
|
||||
uint16 version;
|
||||
uint64 abbrev_offset;
|
||||
uint8 address_size;
|
||||
} header_;
|
||||
|
||||
// Reads the DWARF2/3 header for this compilation unit.
|
||||
void ReadHeader();
|
||||
|
||||
// Reads the DWARF2/3 abbreviations for this compilation unit
|
||||
void ReadAbbrevs();
|
||||
|
||||
// Processes a single DIE for this compilation unit and return a new
|
||||
// pointer just past the end of it
|
||||
const uint8_t *ProcessDIE(uint64 dieoffset,
|
||||
const uint8_t *start,
|
||||
const Abbrev& abbrev);
|
||||
|
||||
// Processes a single attribute and return a new pointer just past the
|
||||
// end of it
|
||||
const uint8_t *ProcessAttribute(uint64 dieoffset,
|
||||
const uint8_t *start,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form);
|
||||
|
||||
// Processes all DIEs for this compilation unit
|
||||
void ProcessDIEs();
|
||||
|
||||
// Skips the die with attributes specified in ABBREV starting at
|
||||
// START, and return the new place to position the stream to.
|
||||
const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
|
||||
|
||||
// Skips the attribute starting at START, with FORM, and return the
|
||||
// new place to position the stream to.
|
||||
const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
|
||||
|
||||
// Offset from section start is the offset of this compilation unit
|
||||
// from the beginning of the .debug_info section.
|
||||
uint64 offset_from_section_start_;
|
||||
|
||||
// buffer is the buffer for our CU, starting at .debug_info + offset
|
||||
// passed in from constructor.
|
||||
// after_header points to right after the compilation unit header.
|
||||
const uint8_t *buffer_;
|
||||
uint64 buffer_length_;
|
||||
const uint8_t *after_header_;
|
||||
|
||||
// The associated ByteReader that handles endianness issues for us
|
||||
ByteReader* reader_;
|
||||
|
||||
// The map of sections in our file to buffers containing their data
|
||||
const SectionMap& sections_;
|
||||
|
||||
// The associated handler to call processing functions in
|
||||
Dwarf2Handler* handler_;
|
||||
|
||||
// Set of DWARF2/3 abbreviations for this compilation unit. Indexed
|
||||
// by abbreviation number, which means that abbrevs_[0] is not
|
||||
// valid.
|
||||
std::vector<Abbrev>* abbrevs_;
|
||||
|
||||
// String section buffer and length, if we have a string section.
|
||||
// This is here to avoid doing a section lookup for strings in
|
||||
// ProcessAttribute, which is in the hot path for DWARF2 reading.
|
||||
const uint8_t *string_buffer_;
|
||||
uint64 string_buffer_length_;
|
||||
};
|
||||
|
||||
// This class is the main interface between the reader and the
|
||||
// client. The virtual functions inside this get called for
|
||||
// interesting events that happen during DWARF2 reading.
|
||||
// The default implementation skips everything.
|
||||
|
||||
class Dwarf2Handler {
|
||||
public:
|
||||
Dwarf2Handler() { }
|
||||
@ -342,6 +204,19 @@ class Dwarf2Handler {
|
||||
uint8 offset_size, uint64 cu_length,
|
||||
uint8 dwarf_version) { return false; }
|
||||
|
||||
// When processing a skeleton compilation unit, resulting from a split
|
||||
// DWARF compilation, once the skeleton debug info has been read,
|
||||
// the reader will call this function to ask the client if it needs
|
||||
// the full debug info from the .dwo or .dwp file. Return true if
|
||||
// you need it, or false to skip processing the split debug info.
|
||||
virtual bool NeedSplitDebugInfo() { return true; }
|
||||
|
||||
// Start to process a split compilation unit at OFFSET from the beginning of
|
||||
// the debug_info section in the .dwp/.dwo file. Return false if you would
|
||||
// like to skip this compilation unit.
|
||||
virtual bool StartSplitCompilationUnit(uint64 offset,
|
||||
uint64 cu_length) { return false; }
|
||||
|
||||
// Start to process a DIE at OFFSET from the beginning of the .debug_info
|
||||
// section. Return false if you would like to skip this DIE.
|
||||
virtual bool StartDIE(uint64 offset, enum DwarfTag tag) { return false; }
|
||||
@ -412,6 +287,367 @@ class Dwarf2Handler {
|
||||
|
||||
};
|
||||
|
||||
// The base of DWARF2/3 debug info is a DIE (Debugging Information
|
||||
// Entry.
|
||||
// DWARF groups DIE's into a tree and calls the root of this tree a
|
||||
// "compilation unit". Most of the time, there is one compilation
|
||||
// unit in the .debug_info section for each file that had debug info
|
||||
// generated.
|
||||
// Each DIE consists of
|
||||
|
||||
// 1. a tag specifying a thing that is being described (ie
|
||||
// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
|
||||
// 2. attributes (such as DW_AT_location for location in memory,
|
||||
// DW_AT_name for name), and data for each attribute.
|
||||
// 3. A flag saying whether the DIE has children or not
|
||||
|
||||
// In order to gain some amount of compression, the format of
|
||||
// each DIE (tag name, attributes and data forms for the attributes)
|
||||
// are stored in a separate table called the "abbreviation table".
|
||||
// This is done because a large number of DIEs have the exact same tag
|
||||
// and list of attributes, but different data for those attributes.
|
||||
// As a result, the .debug_info section is just a stream of data, and
|
||||
// requires reading of the .debug_abbrev section to say what the data
|
||||
// means.
|
||||
|
||||
// As a warning to the user, it should be noted that the reason for
|
||||
// using absolute offsets from the beginning of .debug_info is that
|
||||
// DWARF2/3 supports referencing DIE's from other DIE's by their offset
|
||||
// from either the current compilation unit start, *or* the beginning
|
||||
// of the .debug_info section. This means it is possible to reference
|
||||
// a DIE in one compilation unit from a DIE in another compilation
|
||||
// unit. This style of reference is usually used to eliminate
|
||||
// duplicated information that occurs across compilation
|
||||
// units, such as base types, etc. GCC 3.4+ support this with
|
||||
// -feliminate-dwarf2-dups. Other toolchains will sometimes do
|
||||
// duplicate elimination in the linker.
|
||||
|
||||
class CompilationUnit {
|
||||
public:
|
||||
|
||||
// Initialize a compilation unit. This requires a map of sections,
|
||||
// the offset of this compilation unit in the .debug_info section, a
|
||||
// ByteReader, and a Dwarf2Handler class to call callbacks in.
|
||||
CompilationUnit(const string& path, const SectionMap& sections, uint64 offset,
|
||||
ByteReader* reader, Dwarf2Handler* handler);
|
||||
virtual ~CompilationUnit() {
|
||||
if (abbrevs_) delete abbrevs_;
|
||||
}
|
||||
|
||||
// Initialize a compilation unit from a .dwo or .dwp file.
|
||||
// In this case, we need the .debug_addr section from the
|
||||
// executable file that contains the corresponding skeleton
|
||||
// compilation unit. We also inherit the Dwarf2Handler from
|
||||
// the executable file, and call it as if we were still
|
||||
// processing the original compilation unit.
|
||||
void SetSplitDwarf(const uint8_t* addr_buffer, uint64 addr_buffer_length,
|
||||
uint64 addr_base, uint64 ranges_base, uint64 dwo_id);
|
||||
|
||||
// Begin reading a Dwarf2 compilation unit, and calling the
|
||||
// callbacks in the Dwarf2Handler
|
||||
|
||||
// Return the full length of the compilation unit, including
|
||||
// headers. This plus the starting offset passed to the constructor
|
||||
// is the offset of the end of the compilation unit --- and the
|
||||
// start of the next compilation unit, if there is one.
|
||||
uint64 Start();
|
||||
|
||||
private:
|
||||
|
||||
// This struct represents a single DWARF2/3 abbreviation
|
||||
// The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
|
||||
// tag and a list of attributes, as well as the data form of each attribute.
|
||||
struct Abbrev {
|
||||
uint64 number;
|
||||
enum DwarfTag tag;
|
||||
bool has_children;
|
||||
AttributeList attributes;
|
||||
};
|
||||
|
||||
// A DWARF2/3 compilation unit header. This is not the same size as
|
||||
// in the actual file, as the one in the file may have a 32 bit or
|
||||
// 64 bit length.
|
||||
struct CompilationUnitHeader {
|
||||
uint64 length;
|
||||
uint16 version;
|
||||
uint64 abbrev_offset;
|
||||
uint8 address_size;
|
||||
} header_;
|
||||
|
||||
// Reads the DWARF2/3 header for this compilation unit.
|
||||
void ReadHeader();
|
||||
|
||||
// Reads the DWARF2/3 abbreviations for this compilation unit
|
||||
void ReadAbbrevs();
|
||||
|
||||
// Processes a single DIE for this compilation unit and return a new
|
||||
// pointer just past the end of it
|
||||
const uint8_t *ProcessDIE(uint64 dieoffset,
|
||||
const uint8_t *start,
|
||||
const Abbrev& abbrev);
|
||||
|
||||
// Processes a single attribute and return a new pointer just past the
|
||||
// end of it
|
||||
const uint8_t *ProcessAttribute(uint64 dieoffset,
|
||||
const uint8_t *start,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form);
|
||||
|
||||
// Called when we have an attribute with unsigned data to give to
|
||||
// our handler. The attribute is for the DIE at OFFSET from the
|
||||
// beginning of compilation unit, has a name of ATTR, a form of
|
||||
// FORM, and the actual data of the attribute is in DATA.
|
||||
// If we see a DW_AT_GNU_dwo_id attribute, save the value so that
|
||||
// we can find the debug info in a .dwo or .dwp file.
|
||||
void ProcessAttributeUnsigned(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data) {
|
||||
if (attr == DW_AT_GNU_dwo_id) {
|
||||
dwo_id_ = data;
|
||||
}
|
||||
else if (attr == DW_AT_GNU_addr_base) {
|
||||
addr_base_ = data;
|
||||
}
|
||||
else if (attr == DW_AT_GNU_ranges_base) {
|
||||
ranges_base_ = data;
|
||||
}
|
||||
// TODO(yunlian): When we add DW_AT_ranges_base from DWARF-5,
|
||||
// that base will apply to DW_AT_ranges attributes in the
|
||||
// skeleton CU as well as in the .dwo/.dwp files.
|
||||
else if (attr == DW_AT_ranges && is_split_dwarf_) {
|
||||
data += ranges_base_;
|
||||
}
|
||||
handler_->ProcessAttributeUnsigned(offset, attr, form, data);
|
||||
}
|
||||
|
||||
// Called when we have an attribute with signed data to give to
|
||||
// our handler. The attribute is for the DIE at OFFSET from the
|
||||
// beginning of compilation unit, has a name of ATTR, a form of
|
||||
// FORM, and the actual data of the attribute is in DATA.
|
||||
void ProcessAttributeSigned(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
int64 data) {
|
||||
handler_->ProcessAttributeSigned(offset, attr, form, data);
|
||||
}
|
||||
|
||||
// Called when we have an attribute with a buffer of data to give to
|
||||
// our handler. The attribute is for the DIE at OFFSET from the
|
||||
// beginning of compilation unit, has a name of ATTR, a form of
|
||||
// FORM, and the actual data of the attribute is in DATA, and the
|
||||
// length of the buffer is LENGTH.
|
||||
void ProcessAttributeBuffer(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const uint8_t* data,
|
||||
uint64 len) {
|
||||
handler_->ProcessAttributeBuffer(offset, attr, form, data, len);
|
||||
}
|
||||
|
||||
// Called when we have an attribute with string data to give to
|
||||
// our handler. The attribute is for the DIE at OFFSET from the
|
||||
// beginning of compilation unit, has a name of ATTR, a form of
|
||||
// FORM, and the actual data of the attribute is in DATA.
|
||||
// If we see a DW_AT_GNU_dwo_name attribute, save the value so
|
||||
// that we can find the debug info in a .dwo or .dwp file.
|
||||
void ProcessAttributeString(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const char* data) {
|
||||
if (attr == DW_AT_GNU_dwo_name)
|
||||
dwo_name_ = data;
|
||||
handler_->ProcessAttributeString(offset, attr, form, data);
|
||||
}
|
||||
|
||||
// Processes all DIEs for this compilation unit
|
||||
void ProcessDIEs();
|
||||
|
||||
// Skips the die with attributes specified in ABBREV starting at
|
||||
// START, and return the new place to position the stream to.
|
||||
const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
|
||||
|
||||
// Skips the attribute starting at START, with FORM, and return the
|
||||
// new place to position the stream to.
|
||||
const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
|
||||
|
||||
// Process the actual debug information in a split DWARF file.
|
||||
void ProcessSplitDwarf();
|
||||
|
||||
// Read the debug sections from a .dwo file.
|
||||
void ReadDebugSectionsFromDwo(ElfReader* elf_reader,
|
||||
SectionMap* sections);
|
||||
|
||||
// Path of the file containing the debug information.
|
||||
const string path_;
|
||||
|
||||
// Offset from section start is the offset of this compilation unit
|
||||
// from the beginning of the .debug_info section.
|
||||
uint64 offset_from_section_start_;
|
||||
|
||||
// buffer is the buffer for our CU, starting at .debug_info + offset
|
||||
// passed in from constructor.
|
||||
// after_header points to right after the compilation unit header.
|
||||
const uint8_t *buffer_;
|
||||
uint64 buffer_length_;
|
||||
const uint8_t *after_header_;
|
||||
|
||||
// The associated ByteReader that handles endianness issues for us
|
||||
ByteReader* reader_;
|
||||
|
||||
// The map of sections in our file to buffers containing their data
|
||||
const SectionMap& sections_;
|
||||
|
||||
// The associated handler to call processing functions in
|
||||
Dwarf2Handler* handler_;
|
||||
|
||||
// Set of DWARF2/3 abbreviations for this compilation unit. Indexed
|
||||
// by abbreviation number, which means that abbrevs_[0] is not
|
||||
// valid.
|
||||
std::vector<Abbrev>* abbrevs_;
|
||||
|
||||
// String section buffer and length, if we have a string section.
|
||||
// This is here to avoid doing a section lookup for strings in
|
||||
// ProcessAttribute, which is in the hot path for DWARF2 reading.
|
||||
const uint8_t *string_buffer_;
|
||||
uint64 string_buffer_length_;
|
||||
|
||||
// String offsets section buffer and length, if we have a string offsets
|
||||
// section (.debug_str_offsets or .debug_str_offsets.dwo).
|
||||
const uint8_t* str_offsets_buffer_;
|
||||
uint64 str_offsets_buffer_length_;
|
||||
|
||||
// Address section buffer and length, if we have an address section
|
||||
// (.debug_addr).
|
||||
const uint8_t* addr_buffer_;
|
||||
uint64 addr_buffer_length_;
|
||||
|
||||
// Flag indicating whether this compilation unit is part of a .dwo
|
||||
// or .dwp file. If true, we are reading this unit because a
|
||||
// skeleton compilation unit in an executable file had a
|
||||
// DW_AT_GNU_dwo_name or DW_AT_GNU_dwo_id attribute.
|
||||
// In a .dwo file, we expect the string offsets section to
|
||||
// have a ".dwo" suffix, and we will use the ".debug_addr" section
|
||||
// associated with the skeleton compilation unit.
|
||||
bool is_split_dwarf_;
|
||||
|
||||
// The value of the DW_AT_GNU_dwo_id attribute, if any.
|
||||
uint64 dwo_id_;
|
||||
|
||||
// The value of the DW_AT_GNU_dwo_name attribute, if any.
|
||||
const char* dwo_name_;
|
||||
|
||||
// If this is a split DWARF CU, the value of the DW_AT_GNU_dwo_id attribute
|
||||
// from the skeleton CU.
|
||||
uint64 skeleton_dwo_id_;
|
||||
|
||||
// The value of the DW_AT_GNU_ranges_base attribute, if any.
|
||||
uint64 ranges_base_;
|
||||
|
||||
// The value of the DW_AT_GNU_addr_base attribute, if any.
|
||||
uint64 addr_base_;
|
||||
|
||||
// True if we have already looked for a .dwp file.
|
||||
bool have_checked_for_dwp_;
|
||||
|
||||
// Path to the .dwp file.
|
||||
string dwp_path_;
|
||||
|
||||
// ByteReader for the DWP file.
|
||||
std::unique_ptr<ByteReader> dwp_byte_reader_;
|
||||
|
||||
// DWP reader.
|
||||
std::unique_ptr<DwpReader> dwp_reader_;
|
||||
};
|
||||
|
||||
// A Reader for a .dwp file. Supports the fetching of DWARF debug
|
||||
// info for a given dwo_id.
|
||||
//
|
||||
// There are two versions of .dwp files. In both versions, the
|
||||
// .dwp file is an ELF file containing only debug sections.
|
||||
// In Version 1, the file contains many copies of each debug
|
||||
// section, one for each .dwo file that is packaged in the .dwp
|
||||
// file, and the .debug_cu_index section maps from the dwo_id
|
||||
// to a set of section indexes. In Version 2, the file contains
|
||||
// one of each debug section, and the .debug_cu_index section
|
||||
// maps from the dwo_id to a set of offsets and lengths that
|
||||
// identify each .dwo file's contribution to the larger sections.
|
||||
|
||||
class DwpReader {
|
||||
public:
|
||||
DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader);
|
||||
|
||||
~DwpReader();
|
||||
|
||||
// Read the CU index and initialize data members.
|
||||
void Initialize();
|
||||
|
||||
// Read the debug sections for the given dwo_id.
|
||||
void ReadDebugSectionsForCU(uint64 dwo_id, SectionMap* sections);
|
||||
|
||||
private:
|
||||
// Search a v1 hash table for "dwo_id". Returns the slot index
|
||||
// where the dwo_id was found, or -1 if it was not found.
|
||||
int LookupCU(uint64 dwo_id);
|
||||
|
||||
// Search a v2 hash table for "dwo_id". Returns the row index
|
||||
// in the offsets and sizes tables, or 0 if it was not found.
|
||||
uint32 LookupCUv2(uint64 dwo_id);
|
||||
|
||||
// The ELF reader for the .dwp file.
|
||||
ElfReader* elf_reader_;
|
||||
|
||||
// The ByteReader for the .dwp file.
|
||||
const ByteReader& byte_reader_;
|
||||
|
||||
// Pointer to the .debug_cu_index section.
|
||||
const char* cu_index_;
|
||||
|
||||
// Size of the .debug_cu_index section.
|
||||
size_t cu_index_size_;
|
||||
|
||||
// Pointer to the .debug_str.dwo section.
|
||||
const char* string_buffer_;
|
||||
|
||||
// Size of the .debug_str.dwo section.
|
||||
size_t string_buffer_size_;
|
||||
|
||||
// Version of the .dwp file. We support versions 1 and 2 currently.
|
||||
int version_;
|
||||
|
||||
// Number of columns in the section tables (version 2).
|
||||
unsigned int ncolumns_;
|
||||
|
||||
// Number of units in the section tables (version 2).
|
||||
unsigned int nunits_;
|
||||
|
||||
// Number of slots in the hash table.
|
||||
unsigned int nslots_;
|
||||
|
||||
// Pointer to the beginning of the hash table.
|
||||
const char* phash_;
|
||||
|
||||
// Pointer to the beginning of the index table.
|
||||
const char* pindex_;
|
||||
|
||||
// Pointer to the beginning of the section index pool (version 1).
|
||||
const char* shndx_pool_;
|
||||
|
||||
// Pointer to the beginning of the section offset table (version 2).
|
||||
const char* offset_table_;
|
||||
|
||||
// Pointer to the beginning of the section size table (version 2).
|
||||
const char* size_table_;
|
||||
|
||||
// Contents of the sections of interest (version 2).
|
||||
const char* abbrev_data_;
|
||||
size_t abbrev_size_;
|
||||
const char* info_data_;
|
||||
size_t info_size_;
|
||||
const char* str_offsets_data_;
|
||||
size_t str_offsets_size_;
|
||||
};
|
||||
|
||||
// This class is a reader for DWARF's Call Frame Information. CFI
|
||||
// describes how to unwind stack frames --- even for functions that do
|
||||
// not follow fixed conventions for saving registers, whose frame size
|
||||
|
@ -199,7 +199,7 @@ TEST_P(DwarfHeader, Header) {
|
||||
|
||||
ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
|
||||
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
|
||||
CompilationUnit parser(MakeSectionMap(), 0, &byte_reader, &handler);
|
||||
CompilationUnit parser("", MakeSectionMap(), 0, &byte_reader, &handler);
|
||||
EXPECT_EQ(parser.Start(), info_contents.size());
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ struct DwarfFormsFixture: public DIEFixture {
|
||||
void ParseCompilationUnit(const DwarfHeaderParams ¶ms, uint64 offset=0) {
|
||||
ByteReader byte_reader(params.endianness == kLittleEndian ?
|
||||
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
|
||||
CompilationUnit parser(MakeSectionMap(), offset, &byte_reader, &handler);
|
||||
CompilationUnit parser("", MakeSectionMap(), offset, &byte_reader, &handler);
|
||||
EXPECT_EQ(offset + parser.Start(), info_contents.size());
|
||||
}
|
||||
|
||||
|
1273
src/common/dwarf/elf_reader.cc
Normal file
1273
src/common/dwarf/elf_reader.cc
Normal file
File diff suppressed because it is too large
Load Diff
166
src/common/dwarf/elf_reader.h
Normal file
166
src/common/dwarf/elf_reader.h
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright 2005 Google Inc. All Rights Reserved.
|
||||
// Author: chatham@google.com (Andrew Chatham)
|
||||
// Author: satorux@google.com (Satoru Takabayashi)
|
||||
//
|
||||
// ElfReader handles reading in ELF. It can extract symbols from the
|
||||
// current process, which may be used to symbolize stack traces
|
||||
// without having to make a potentially dangerous call to fork().
|
||||
//
|
||||
// ElfReader dynamically allocates memory, so it is not appropriate to
|
||||
// use once the address space might be corrupted, such as during
|
||||
// process death.
|
||||
//
|
||||
// ElfReader supports both 32-bit and 64-bit ELF binaries.
|
||||
|
||||
#ifndef COMMON_DWARF_ELF_READER_H__
|
||||
#define COMMON_DWARF_ELF_READER_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/dwarf/types.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
class SymbolMap;
|
||||
class Elf32;
|
||||
class Elf64;
|
||||
template<typename ElfArch>
|
||||
class ElfReaderImpl;
|
||||
|
||||
class ElfReader {
|
||||
public:
|
||||
explicit ElfReader(const string &path);
|
||||
~ElfReader();
|
||||
|
||||
// Parse the ELF prologue of this file and return whether it was
|
||||
// successfully parsed and matches the word size and byte order of
|
||||
// the current process.
|
||||
bool IsNativeElfFile() const;
|
||||
|
||||
// Similar to IsNativeElfFile but checks if it's a 32-bit ELF file.
|
||||
bool IsElf32File() const;
|
||||
|
||||
// Similar to IsNativeElfFile but checks if it's a 64-bit ELF file.
|
||||
bool IsElf64File() const;
|
||||
|
||||
// Checks if it's an ELF file of type ET_DYN (shared object file).
|
||||
bool IsDynamicSharedObject();
|
||||
|
||||
// Add symbols in the given ELF file into the provided SymbolMap,
|
||||
// assuming that the file has been loaded into the specified
|
||||
// offset.
|
||||
//
|
||||
// The remaining arguments are typically taken from a
|
||||
// ProcMapsIterator (base/sysinfo.h) and describe which portions of
|
||||
// the ELF file are mapped into which parts of memory:
|
||||
//
|
||||
// mem_offset - position at which the segment is mapped into memory
|
||||
// file_offset - offset in the file where the mapping begins
|
||||
// length - length of the mapped segment
|
||||
void AddSymbols(SymbolMap *symbols,
|
||||
uint64 mem_offset, uint64 file_offset,
|
||||
uint64 length);
|
||||
|
||||
class SymbolSink {
|
||||
public:
|
||||
virtual ~SymbolSink() {}
|
||||
virtual void AddSymbol(const char *name, uint64 address, uint64 size) = 0;
|
||||
};
|
||||
|
||||
// Like AddSymbols above, but with no address correction.
|
||||
// Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section.
|
||||
void VisitSymbols(SymbolSink *sink);
|
||||
|
||||
// Like VisitSymbols above, but for a specific symbol binding/type.
|
||||
// A negative value for the binding and type parameters means any
|
||||
// binding or type.
|
||||
void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type);
|
||||
|
||||
// Like VisitSymbols above but can optionally export raw symbol values instead
|
||||
// of adjusted ones.
|
||||
void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type,
|
||||
bool get_raw_symbol_values);
|
||||
|
||||
// p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
|
||||
// segments are present. This is the address an ELF image was linked
|
||||
// (by static linker) to be loaded at. Usually (but not always) 0 for
|
||||
// shared libraries and position-independent executables.
|
||||
uint64 VaddrOfFirstLoadSegment();
|
||||
|
||||
// Return the name of section "shndx". Returns NULL if the section
|
||||
// is not found.
|
||||
const char *GetSectionName(int shndx);
|
||||
|
||||
// Return the number of sections in the given ELF file.
|
||||
uint64 GetNumSections();
|
||||
|
||||
// Get section "shndx" from the given ELF file. On success, return
|
||||
// the pointer to the section and store the size in "size".
|
||||
// On error, return NULL. The returned section data is only valid
|
||||
// until the ElfReader gets destroyed.
|
||||
const char *GetSectionByIndex(int shndx, size_t *size);
|
||||
|
||||
// Get section with "section_name" (ex. ".text", ".symtab") in the
|
||||
// given ELF file. On success, return the pointer to the section
|
||||
// and store the size in "size". On error, return NULL. The
|
||||
// returned section data is only valid until the ElfReader gets
|
||||
// destroyed.
|
||||
const char *GetSectionByName(const string §ion_name, size_t *size);
|
||||
|
||||
// This is like GetSectionByName() but it returns a lot of extra information
|
||||
// about the section. The SectionInfo structure is almost identical to
|
||||
// the typedef struct Elf64_Shdr defined in <elf.h>, but is redefined
|
||||
// here so that the many short macro names in <elf.h> don't have to be
|
||||
// added to our already cluttered namespace.
|
||||
struct SectionInfo {
|
||||
uint32 type; // Section type (SHT_xxx constant from elf.h).
|
||||
uint64 flags; // Section flags (SHF_xxx constants from elf.h).
|
||||
uint64 addr; // Section virtual address at execution.
|
||||
uint64 offset; // Section file offset.
|
||||
uint64 size; // Section size in bytes.
|
||||
uint32 link; // Link to another section.
|
||||
uint32 info; // Additional section information.
|
||||
uint64 addralign; // Section alignment.
|
||||
uint64 entsize; // Entry size if section holds a table.
|
||||
};
|
||||
const char *GetSectionInfoByName(const string §ion_name,
|
||||
SectionInfo *info);
|
||||
|
||||
// Check if "path" is an ELF binary that has not been stripped of symbol
|
||||
// tables. This function supports both 32-bit and 64-bit ELF binaries.
|
||||
static bool IsNonStrippedELFBinary(const string &path);
|
||||
|
||||
// Check if "path" is an ELF binary that has not been stripped of debug
|
||||
// info. Unlike IsNonStrippedELFBinary, this function will return
|
||||
// false for binaries passed through "strip -S".
|
||||
static bool IsNonDebugStrippedELFBinary(const string &path);
|
||||
|
||||
// Match a requested section name with the section name as it
|
||||
// appears in the elf-file, adjusting for compressed debug section
|
||||
// names. For example, returns true if name == ".debug_abbrev" and
|
||||
// sh_name == ".zdebug_abbrev"
|
||||
static bool SectionNamesMatch(const string &name, const string &sh_name);
|
||||
|
||||
private:
|
||||
// Lazily initialize impl32_ and return it.
|
||||
ElfReaderImpl<Elf32> *GetImpl32();
|
||||
// Ditto for impl64_.
|
||||
ElfReaderImpl<Elf64> *GetImpl64();
|
||||
|
||||
// Path of the file we're reading.
|
||||
const string path_;
|
||||
// Read-only file descriptor for the file. May be -1 if there was an
|
||||
// error during open.
|
||||
int fd_;
|
||||
ElfReaderImpl<Elf32> *impl32_;
|
||||
ElfReaderImpl<Elf64> *impl64_;
|
||||
};
|
||||
|
||||
} // namespace dwarf2reader
|
||||
|
||||
#endif // COMMON_DWARF_ELF_READER_H__
|
@ -384,17 +384,17 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
|
||||
qualified_name = &specification_->qualified_name;
|
||||
}
|
||||
|
||||
const string *unqualified_name;
|
||||
const string *unqualified_name = NULL;
|
||||
const string *enclosing_name;
|
||||
if (!qualified_name) {
|
||||
// Find our unqualified name. If the DIE has its own DW_AT_name
|
||||
// attribute, then use that; otherwise, check our specification.
|
||||
if (name_attribute_.empty() && specification_)
|
||||
unqualified_name = &specification_->unqualified_name;
|
||||
else
|
||||
// Find the unqualified name. If the DIE has its own DW_AT_name
|
||||
// attribute, then use that; otherwise, check the specification.
|
||||
if (!name_attribute_.empty())
|
||||
unqualified_name = &name_attribute_;
|
||||
else if (specification_)
|
||||
unqualified_name = &specification_->unqualified_name;
|
||||
|
||||
// Find the name of our enclosing context. If we have a
|
||||
// Find the name of the enclosing context. If this DIE has a
|
||||
// specification, it's the specification's enclosing context that
|
||||
// counts; otherwise, use this DIE's context.
|
||||
if (specification_)
|
||||
@ -408,7 +408,7 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
|
||||
string return_value;
|
||||
if (qualified_name) {
|
||||
return_value = *qualified_name;
|
||||
} else {
|
||||
} else if (unqualified_name && enclosing_name) {
|
||||
// Combine the enclosing name and unqualified name to produce our
|
||||
// own fully-qualified name.
|
||||
return_value = cu_context_->language->MakeQualifiedName(*enclosing_name,
|
||||
@ -417,7 +417,8 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
|
||||
|
||||
// If this DIE was marked as a declaration, record its names in the
|
||||
// specification table.
|
||||
if (declaration_) {
|
||||
if ((declaration_ && qualified_name) ||
|
||||
(unqualified_name && enclosing_name)) {
|
||||
Specification spec;
|
||||
if (qualified_name) {
|
||||
spec.qualified_name = *qualified_name;
|
||||
|
@ -1323,6 +1323,29 @@ TEST_F(Specifications, InlineFunction) {
|
||||
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||
}
|
||||
|
||||
// An inline function in a namespace should correctly derive its
|
||||
// name from its abstract origin, and not just the namespace name.
|
||||
TEST_F(Specifications, InlineFunctionInNamespace) {
|
||||
PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
|
||||
|
||||
StartCU();
|
||||
DIEHandler* space_handler
|
||||
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
|
||||
"Namespace");
|
||||
ASSERT_TRUE(space_handler != NULL);
|
||||
AbstractInstanceDIE(space_handler, 0x1e8dac5d507ed7abULL,
|
||||
dwarf2reader::DW_INL_inlined, 0LL, "func-name");
|
||||
DefineInlineInstanceDIE(space_handler, "", 0x1e8dac5d507ed7abULL,
|
||||
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||
space_handler->Finish();
|
||||
delete space_handler;
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
TestFunction(0, "Namespace::func-name",
|
||||
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||
}
|
||||
|
||||
// Check name construction for a long chain containing each combination of:
|
||||
// - struct, union, class, namespace
|
||||
// - direct and definition
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "common/linux/elfutils-inl.h"
|
||||
#include "common/linux/elf_symbols_to_module.h"
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/memory.h"
|
||||
#include "common/module.h"
|
||||
#include "common/scoped_ptr.h"
|
||||
#ifndef NO_STABS_SUPPORT
|
||||
@ -82,14 +83,18 @@ using google_breakpad::DwarfLineToModule;
|
||||
using google_breakpad::ElfClass;
|
||||
using google_breakpad::ElfClass32;
|
||||
using google_breakpad::ElfClass64;
|
||||
using google_breakpad::FileID;
|
||||
using google_breakpad::FindElfSectionByName;
|
||||
using google_breakpad::GetOffset;
|
||||
using google_breakpad::IsValidElf;
|
||||
using google_breakpad::kDefaultBuildIdSize;
|
||||
using google_breakpad::Module;
|
||||
using google_breakpad::PageAllocator;
|
||||
#ifndef NO_STABS_SUPPORT
|
||||
using google_breakpad::StabsToModule;
|
||||
#endif
|
||||
using google_breakpad::scoped_ptr;
|
||||
using google_breakpad::wasteful_vector;
|
||||
|
||||
// Define AARCH64 ELF architecture if host machine does not include this define.
|
||||
#ifndef EM_AARCH64
|
||||
@ -283,7 +288,8 @@ bool LoadDwarf(const string& dwarf_filename,
|
||||
// Make a Dwarf2Handler that drives the DIEHandler.
|
||||
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
|
||||
// Make a DWARF parser for the compilation unit at OFFSET.
|
||||
dwarf2reader::CompilationUnit reader(file_context.section_map(),
|
||||
dwarf2reader::CompilationUnit reader(dwarf_filename,
|
||||
file_context.section_map(),
|
||||
offset,
|
||||
&byte_reader,
|
||||
&die_dispatcher);
|
||||
@ -684,32 +690,61 @@ bool LoadSymbols(const string& obj_file,
|
||||
}
|
||||
|
||||
// See if there are export symbols available.
|
||||
const Shdr* dynsym_section =
|
||||
FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
const Shdr* dynstr_section =
|
||||
FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
if (dynsym_section && dynstr_section) {
|
||||
info->LoadedSection(".dynsym");
|
||||
const Shdr* symtab_section =
|
||||
FindElfSectionByName<ElfClass>(".symtab", SHT_SYMTAB,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
const Shdr* strtab_section =
|
||||
FindElfSectionByName<ElfClass>(".strtab", SHT_STRTAB,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
if (symtab_section && strtab_section) {
|
||||
info->LoadedSection(".symtab");
|
||||
|
||||
const uint8_t* dynsyms =
|
||||
const uint8_t* symtab =
|
||||
GetOffset<ElfClass, uint8_t>(elf_header,
|
||||
dynsym_section->sh_offset);
|
||||
const uint8_t* dynstrs =
|
||||
symtab_section->sh_offset);
|
||||
const uint8_t* strtab =
|
||||
GetOffset<ElfClass, uint8_t>(elf_header,
|
||||
dynstr_section->sh_offset);
|
||||
strtab_section->sh_offset);
|
||||
bool result =
|
||||
ELFSymbolsToModule(dynsyms,
|
||||
dynsym_section->sh_size,
|
||||
dynstrs,
|
||||
dynstr_section->sh_size,
|
||||
ELFSymbolsToModule(symtab,
|
||||
symtab_section->sh_size,
|
||||
strtab,
|
||||
strtab_section->sh_size,
|
||||
big_endian,
|
||||
ElfClass::kAddrSize,
|
||||
module);
|
||||
found_usable_info = found_usable_info || result;
|
||||
} else {
|
||||
// Look in dynsym only if full symbol table was not available.
|
||||
const Shdr* dynsym_section =
|
||||
FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
const Shdr* dynstr_section =
|
||||
FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
if (dynsym_section && dynstr_section) {
|
||||
info->LoadedSection(".dynsym");
|
||||
|
||||
const uint8_t* dynsyms =
|
||||
GetOffset<ElfClass, uint8_t>(elf_header,
|
||||
dynsym_section->sh_offset);
|
||||
const uint8_t* dynstrs =
|
||||
GetOffset<ElfClass, uint8_t>(elf_header,
|
||||
dynstr_section->sh_offset);
|
||||
bool result =
|
||||
ELFSymbolsToModule(dynsyms,
|
||||
dynsym_section->sh_size,
|
||||
dynstrs,
|
||||
dynstr_section->sh_size,
|
||||
big_endian,
|
||||
ElfClass::kAddrSize,
|
||||
module);
|
||||
found_usable_info = found_usable_info || result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -825,25 +860,6 @@ const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) {
|
||||
}
|
||||
}
|
||||
|
||||
// Format the Elf file identifier in IDENTIFIER as a UUID with the
|
||||
// dashes removed.
|
||||
string FormatIdentifier(unsigned char identifier[16]) {
|
||||
char identifier_str[40];
|
||||
google_breakpad::FileID::ConvertIdentifierToString(
|
||||
identifier,
|
||||
identifier_str,
|
||||
sizeof(identifier_str));
|
||||
string id_no_dash;
|
||||
for (int i = 0; identifier_str[i] != '\0'; ++i)
|
||||
if (identifier_str[i] != '-')
|
||||
id_no_dash += identifier_str[i];
|
||||
// Add an extra "0" by the end. PDB files on Windows have an 'age'
|
||||
// number appended to the end of the file identifier; this isn't
|
||||
// really used or necessary on other platforms, but be consistent.
|
||||
id_no_dash += '0';
|
||||
return id_no_dash;
|
||||
}
|
||||
|
||||
// Return the non-directory portion of FILENAME: the portion after the
|
||||
// last slash, or the whole filename if there are no slashes.
|
||||
string BaseFileName(const string &filename) {
|
||||
@ -886,18 +902,12 @@ bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header,
|
||||
}
|
||||
|
||||
template<typename ElfClass>
|
||||
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||
const string& obj_filename,
|
||||
const std::vector<string>& debug_dirs,
|
||||
const DumpOptions& options,
|
||||
Module** out_module) {
|
||||
typedef typename ElfClass::Ehdr Ehdr;
|
||||
|
||||
*out_module = NULL;
|
||||
|
||||
unsigned char identifier[16];
|
||||
if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header,
|
||||
identifier)) {
|
||||
bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||
const string& obj_filename,
|
||||
scoped_ptr<Module>& module) {
|
||||
PageAllocator allocator;
|
||||
wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
|
||||
if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) {
|
||||
fprintf(stderr, "%s: unable to generate file identifier\n",
|
||||
obj_filename.c_str());
|
||||
return false;
|
||||
@ -910,17 +920,39 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||
return false;
|
||||
}
|
||||
|
||||
string name = BaseFileName(obj_filename);
|
||||
string os = "Linux";
|
||||
// Add an extra "0" at the end. PDB files on Windows have an 'age'
|
||||
// number appended to the end of the file identifier; this isn't
|
||||
// really used or necessary on other platforms, but be consistent.
|
||||
string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0";
|
||||
|
||||
module.reset(new Module(name, os, architecture, id));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ElfClass>
|
||||
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||
const string& obj_filename,
|
||||
const std::vector<string>& debug_dirs,
|
||||
const DumpOptions& options,
|
||||
Module** out_module) {
|
||||
typedef typename ElfClass::Ehdr Ehdr;
|
||||
|
||||
*out_module = NULL;
|
||||
|
||||
scoped_ptr<Module> module;
|
||||
if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Figure out what endianness this file is.
|
||||
bool big_endian;
|
||||
if (!ElfEndianness<ElfClass>(elf_header, &big_endian))
|
||||
return false;
|
||||
|
||||
string name = BaseFileName(obj_filename);
|
||||
string os = "Linux";
|
||||
string id = FormatIdentifier(identifier);
|
||||
|
||||
LoadSymbolsInfo<ElfClass> info(debug_dirs);
|
||||
scoped_ptr<Module> module(new Module(name, os, architecture, id));
|
||||
if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
|
||||
!debug_dirs.empty(), &info,
|
||||
options, module.get())) {
|
||||
@ -935,7 +967,9 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||
if (!LoadELF(debuglink_file, &debug_map_wrapper,
|
||||
reinterpret_cast<void**>(&debug_elf_header)) ||
|
||||
!SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file,
|
||||
obj_filename, architecture, big_endian)) {
|
||||
obj_filename,
|
||||
module->architecture().c_str(),
|
||||
big_endian)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -993,6 +1027,45 @@ bool WriteSymbolFile(const string &obj_file,
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read the selected object file's debugging information, and write out the
|
||||
// header only to |stream|. Return true on success; if an error occurs, report
|
||||
// it and return false.
|
||||
bool WriteSymbolFileHeader(const string& obj_file,
|
||||
std::ostream &sym_stream) {
|
||||
MmapWrapper map_wrapper;
|
||||
void* elf_header = NULL;
|
||||
if (!LoadELF(obj_file, &map_wrapper, &elf_header)) {
|
||||
fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsValidElf(elf_header)) {
|
||||
fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int elfclass = ElfClass(elf_header);
|
||||
scoped_ptr<Module> module;
|
||||
if (elfclass == ELFCLASS32) {
|
||||
if (!InitModuleForElfClass<ElfClass32>(
|
||||
reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, module)) {
|
||||
fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
|
||||
return false;
|
||||
}
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
if (!InitModuleForElfClass<ElfClass64>(
|
||||
reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, module)) {
|
||||
fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unsupported module file: %s\n", obj_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return module->Write(sym_stream, ALL_SYMBOL_DATA);
|
||||
}
|
||||
|
||||
bool ReadSymbolData(const string& obj_file,
|
||||
const std::vector<string>& debug_dirs,
|
||||
const DumpOptions& options,
|
||||
|
@ -67,6 +67,12 @@ bool WriteSymbolFile(const string &obj_file,
|
||||
const DumpOptions& options,
|
||||
std::ostream &sym_stream);
|
||||
|
||||
// Read the selected object file's debugging information, and write out the
|
||||
// header only to |stream|. Return true on success; if an error occurs, report
|
||||
// it and return false.
|
||||
bool WriteSymbolFileHeader(const string& obj_file,
|
||||
std::ostream &sym_stream);
|
||||
|
||||
// As above, but simply return the debugging information in MODULE
|
||||
// instead of writing it to a stream. The caller owns the resulting
|
||||
// Module object and must delete it when finished.
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "common/linux/elf_gnu_compat.h"
|
||||
#include "common/linux/elfutils.h"
|
||||
@ -46,8 +47,13 @@
|
||||
#include "common/linux/memory_mapped_file.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Used in a few places for backwards-compatibility.
|
||||
const size_t kMDGUIDSize = sizeof(MDGUID);
|
||||
|
||||
FileID::FileID(const char* path) : path_(path) {}
|
||||
|
||||
// ELF note name and desc are 32-bits word padded.
|
||||
@ -58,7 +64,7 @@ FileID::FileID(const char* path) : path_(path) {}
|
||||
|
||||
template<typename ElfClass>
|
||||
static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
wasteful_vector<uint8_t>& identifier) {
|
||||
typedef typename ElfClass::Nhdr Nhdr;
|
||||
|
||||
const void* section_end = reinterpret_cast<const char*>(section) + length;
|
||||
@ -76,21 +82,19 @@ static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* build_id = reinterpret_cast<const char*>(note_header) +
|
||||
const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) +
|
||||
sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
|
||||
// Copy as many bits of the build ID as will fit
|
||||
// into the GUID space.
|
||||
my_memset(identifier, 0, kMDGUIDSize);
|
||||
memcpy(identifier, build_id,
|
||||
std::min(kMDGUIDSize, (size_t)note_header->n_descsz));
|
||||
identifier.insert(identifier.end(),
|
||||
build_id,
|
||||
build_id + note_header->n_descsz);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Attempt to locate a .note.gnu.build-id section in an ELF binary
|
||||
// and copy as many bytes of it as will fit into |identifier|.
|
||||
static bool FindElfBuildIDNote(const void *elf_mapped_base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
// and copy it into |identifier|.
|
||||
static bool FindElfBuildIDNote(const void* elf_mapped_base,
|
||||
wasteful_vector<uint8_t>& identifier) {
|
||||
void* note_section;
|
||||
size_t note_size;
|
||||
int elfclass;
|
||||
@ -116,8 +120,10 @@ static bool FindElfBuildIDNote(const void *elf_mapped_base,
|
||||
|
||||
// Attempt to locate the .text section of an ELF binary and generate
|
||||
// a simple hash by XORing the first page worth of bytes into |identifier|.
|
||||
static bool HashElfTextSection(const void *elf_mapped_base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
static bool HashElfTextSection(const void* elf_mapped_base,
|
||||
wasteful_vector<uint8_t>& identifier) {
|
||||
identifier.resize(kMDGUIDSize);
|
||||
|
||||
void* text_section;
|
||||
size_t text_size;
|
||||
if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
|
||||
@ -126,7 +132,9 @@ static bool HashElfTextSection(const void *elf_mapped_base,
|
||||
return false;
|
||||
}
|
||||
|
||||
my_memset(identifier, 0, kMDGUIDSize);
|
||||
// Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
|
||||
// function backwards-compatible.
|
||||
my_memset(&identifier[0], 0, kMDGUIDSize);
|
||||
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
|
||||
const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096));
|
||||
while (ptr < ptr_end) {
|
||||
@ -139,7 +147,7 @@ static bool HashElfTextSection(const void *elf_mapped_base,
|
||||
|
||||
// static
|
||||
bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
wasteful_vector<uint8_t>& identifier) {
|
||||
// Look for a build id note first.
|
||||
if (FindElfBuildIDNote(base, identifier))
|
||||
return true;
|
||||
@ -148,7 +156,7 @@ bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
|
||||
return HashElfTextSection(base, identifier);
|
||||
}
|
||||
|
||||
bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
|
||||
bool FileID::ElfFileIdentifier(wasteful_vector<uint8_t>& identifier) {
|
||||
MemoryMappedFile mapped_file(path_.c_str(), 0);
|
||||
if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
|
||||
return false;
|
||||
@ -156,13 +164,16 @@ bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
|
||||
return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
|
||||
}
|
||||
|
||||
// This function is not ever called in an unsafe context, so it's OK
|
||||
// to allocate memory and use libc.
|
||||
// static
|
||||
void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
|
||||
char* buffer, int buffer_length) {
|
||||
uint8_t identifier_swapped[kMDGUIDSize];
|
||||
string FileID::ConvertIdentifierToUUIDString(
|
||||
const wasteful_vector<uint8_t>& identifier) {
|
||||
uint8_t identifier_swapped[kMDGUIDSize] = { 0 };
|
||||
|
||||
// Endian-ness swap to match dump processor expectation.
|
||||
memcpy(identifier_swapped, identifier, kMDGUIDSize);
|
||||
memcpy(identifier_swapped, &identifier[0],
|
||||
std::min(kMDGUIDSize, identifier.size()));
|
||||
uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
|
||||
*data1 = htonl(*data1);
|
||||
uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
|
||||
@ -170,22 +181,13 @@ void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
|
||||
uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
|
||||
*data3 = htons(*data3);
|
||||
|
||||
int buffer_idx = 0;
|
||||
for (unsigned int idx = 0;
|
||||
(buffer_idx < buffer_length) && (idx < kMDGUIDSize);
|
||||
++idx) {
|
||||
int hi = (identifier_swapped[idx] >> 4) & 0x0F;
|
||||
int lo = (identifier_swapped[idx]) & 0x0F;
|
||||
|
||||
if (idx == 4 || idx == 6 || idx == 8 || idx == 10)
|
||||
buffer[buffer_idx++] = '-';
|
||||
|
||||
buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
|
||||
buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
|
||||
string result;
|
||||
for (unsigned int idx = 0; idx < kMDGUIDSize; ++idx) {
|
||||
char buf[3];
|
||||
snprintf(buf, sizeof(buf), "%02X", identifier_swapped[idx]);
|
||||
result.append(buf);
|
||||
}
|
||||
|
||||
// NULL terminate
|
||||
buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -37,10 +37,15 @@
|
||||
#include <string>
|
||||
|
||||
#include "common/linux/guid_creator.h"
|
||||
#include "common/memory.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
static const size_t kMDGUIDSize = sizeof(MDGUID);
|
||||
// GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes,
|
||||
// so this is enough to fit that, which most binaries will use.
|
||||
// This is just a sensible default for auto_wasteful_vector so most
|
||||
// callers can get away with stack allocation.
|
||||
static const size_t kDefaultBuildIdSize = 20;
|
||||
|
||||
class FileID {
|
||||
public:
|
||||
@ -48,25 +53,25 @@ class FileID {
|
||||
~FileID() {}
|
||||
|
||||
// Load the identifier for the elf file path specified in the constructor into
|
||||
// |identifier|. Return false if the identifier could not be created for the
|
||||
// file.
|
||||
// |identifier|.
|
||||
//
|
||||
// The current implementation will look for a .note.gnu.build-id
|
||||
// section and use that as the file id, otherwise it falls back to
|
||||
// XORing the first 4096 bytes of the .text section to generate an identifier.
|
||||
bool ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]);
|
||||
bool ElfFileIdentifier(wasteful_vector<uint8_t>& identifier);
|
||||
|
||||
// Load the identifier for the elf file mapped into memory at |base| into
|
||||
// |identifier|. Return false if the identifier could not be created for the
|
||||
// |identifier|. Return false if the identifier could not be created for this
|
||||
// file.
|
||||
static bool ElfFileIdentifierFromMappedFile(const void* base,
|
||||
uint8_t identifier[kMDGUIDSize]);
|
||||
static bool ElfFileIdentifierFromMappedFile(
|
||||
const void* base,
|
||||
wasteful_vector<uint8_t>& identifier);
|
||||
|
||||
// Convert the |identifier| data to a NULL terminated string. The string will
|
||||
// be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE).
|
||||
// The |buffer| should be at least 37 bytes long to receive all of the data
|
||||
// and termination. Shorter buffers will contain truncated data.
|
||||
static void ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
|
||||
char* buffer, int buffer_length);
|
||||
// Convert the |identifier| data to a string. The string will
|
||||
// be formatted as a UUID in all uppercase without dashes.
|
||||
// (e.g., 22F065BBFC9C49F780FE26A7CEBD7BCE).
|
||||
static std::string ConvertIdentifierToUUIDString(
|
||||
const wasteful_vector<uint8_t>& identifier);
|
||||
|
||||
private:
|
||||
// Storage for the path specified
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/linux/elf_gnu_compat.h"
|
||||
#include "common/linux/elfutils.h"
|
||||
@ -45,13 +46,11 @@
|
||||
#include "breakpad_googletest_includes.h"
|
||||
|
||||
using namespace google_breakpad;
|
||||
using google_breakpad::ElfClass32;
|
||||
using google_breakpad::ElfClass64;
|
||||
using google_breakpad::SafeReadLink;
|
||||
using google_breakpad::synth_elf::ELF;
|
||||
using google_breakpad::synth_elf::Notes;
|
||||
using google_breakpad::test_assembler::kLittleEndian;
|
||||
using google_breakpad::test_assembler::Section;
|
||||
using std::vector;
|
||||
using ::testing::Types;
|
||||
|
||||
namespace {
|
||||
@ -64,6 +63,8 @@ void PopulateSection(Section* section, int size, int prime_number) {
|
||||
section->Append(1, (i % prime_number) % 256);
|
||||
}
|
||||
|
||||
typedef wasteful_vector<uint8_t> id_vector;
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifndef __ANDROID__
|
||||
@ -87,19 +88,20 @@ TEST(FileIDStripTest, StripSelf) {
|
||||
sprintf(cmdline, "strip \"%s\"", templ.c_str());
|
||||
ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
|
||||
|
||||
uint8_t identifier1[sizeof(MDGUID)];
|
||||
uint8_t identifier2[sizeof(MDGUID)];
|
||||
PageAllocator allocator;
|
||||
id_vector identifier1(&allocator, kDefaultBuildIdSize);
|
||||
id_vector identifier2(&allocator, kDefaultBuildIdSize);
|
||||
|
||||
FileID fileid1(exe_name);
|
||||
EXPECT_TRUE(fileid1.ElfFileIdentifier(identifier1));
|
||||
FileID fileid2(templ.c_str());
|
||||
EXPECT_TRUE(fileid2.ElfFileIdentifier(identifier2));
|
||||
char identifier_string1[37];
|
||||
char identifier_string2[37];
|
||||
FileID::ConvertIdentifierToString(identifier1, identifier_string1,
|
||||
37);
|
||||
FileID::ConvertIdentifierToString(identifier2, identifier_string2,
|
||||
37);
|
||||
EXPECT_STREQ(identifier_string1, identifier_string2);
|
||||
|
||||
string identifier_string1 =
|
||||
FileID::ConvertIdentifierToUUIDString(identifier1);
|
||||
string identifier_string2 =
|
||||
FileID::ConvertIdentifierToUUIDString(identifier2);
|
||||
EXPECT_EQ(identifier_string1, identifier_string2);
|
||||
}
|
||||
#endif // !__ANDROID__
|
||||
|
||||
@ -116,8 +118,22 @@ public:
|
||||
elfdata = &elfdata_v[0];
|
||||
}
|
||||
|
||||
id_vector make_vector() {
|
||||
return id_vector(&allocator, kDefaultBuildIdSize);
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
string get_file_id(const uint8_t (&data)[N]) {
|
||||
id_vector expected_identifier(make_vector());
|
||||
expected_identifier.insert(expected_identifier.end(),
|
||||
&data[0],
|
||||
data + N);
|
||||
return FileID::ConvertIdentifierToUUIDString(expected_identifier);
|
||||
}
|
||||
|
||||
vector<uint8_t> elfdata_v;
|
||||
uint8_t* elfdata;
|
||||
PageAllocator allocator;
|
||||
};
|
||||
|
||||
typedef Types<ElfClass32, ElfClass64> ElfClasses;
|
||||
@ -125,10 +141,8 @@ typedef Types<ElfClass32, ElfClass64> ElfClasses;
|
||||
TYPED_TEST_CASE(FileIDTest, ElfClasses);
|
||||
|
||||
TYPED_TEST(FileIDTest, ElfClass) {
|
||||
uint8_t identifier[sizeof(MDGUID)];
|
||||
const char expected_identifier_string[] =
|
||||
"80808080-8080-0000-0000-008080808080";
|
||||
char identifier_string[sizeof(expected_identifier_string)];
|
||||
"80808080808000000000008080808080";
|
||||
const size_t kTextSectionSize = 128;
|
||||
|
||||
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
@ -140,58 +154,106 @@ TYPED_TEST(FileIDTest, ElfClass) {
|
||||
elf.Finish();
|
||||
this->GetElfContents(elf);
|
||||
|
||||
id_vector identifier(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier));
|
||||
|
||||
FileID::ConvertIdentifierToString(identifier, identifier_string,
|
||||
sizeof(identifier_string));
|
||||
EXPECT_STREQ(expected_identifier_string, identifier_string);
|
||||
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
|
||||
EXPECT_EQ(expected_identifier_string, identifier_string);
|
||||
}
|
||||
|
||||
TYPED_TEST(FileIDTest, BuildID) {
|
||||
const uint8_t kExpectedIdentifier[sizeof(MDGUID)] =
|
||||
const uint8_t kExpectedIdentifierBytes[] =
|
||||
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
|
||||
char expected_identifier_string[] =
|
||||
"00000000-0000-0000-0000-000000000000";
|
||||
FileID::ConvertIdentifierToString(kExpectedIdentifier,
|
||||
expected_identifier_string,
|
||||
sizeof(expected_identifier_string));
|
||||
|
||||
uint8_t identifier[sizeof(MDGUID)];
|
||||
char identifier_string[sizeof(expected_identifier_string)];
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13};
|
||||
const string expected_identifier_string =
|
||||
this->get_file_id(kExpectedIdentifierBytes);
|
||||
|
||||
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
Section text(kLittleEndian);
|
||||
text.Append(4096, 0);
|
||||
elf.AddSection(".text", text, SHT_PROGBITS);
|
||||
Notes notes(kLittleEndian);
|
||||
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier,
|
||||
sizeof(kExpectedIdentifier));
|
||||
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
|
||||
sizeof(kExpectedIdentifierBytes));
|
||||
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
|
||||
elf.Finish();
|
||||
this->GetElfContents(elf);
|
||||
|
||||
id_vector identifier(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier));
|
||||
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
|
||||
|
||||
FileID::ConvertIdentifierToString(identifier, identifier_string,
|
||||
sizeof(identifier_string));
|
||||
EXPECT_STREQ(expected_identifier_string, identifier_string);
|
||||
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
|
||||
EXPECT_EQ(expected_identifier_string, identifier_string);
|
||||
}
|
||||
|
||||
// Test that a build id note with fewer bytes than usual is handled.
|
||||
TYPED_TEST(FileIDTest, BuildIDShort) {
|
||||
const uint8_t kExpectedIdentifierBytes[] =
|
||||
{0x00, 0x01, 0x02, 0x03};
|
||||
const string expected_identifier_string =
|
||||
this->get_file_id(kExpectedIdentifierBytes);
|
||||
|
||||
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
Section text(kLittleEndian);
|
||||
text.Append(4096, 0);
|
||||
elf.AddSection(".text", text, SHT_PROGBITS);
|
||||
Notes notes(kLittleEndian);
|
||||
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
|
||||
sizeof(kExpectedIdentifierBytes));
|
||||
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
|
||||
elf.Finish();
|
||||
this->GetElfContents(elf);
|
||||
|
||||
id_vector identifier(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier));
|
||||
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
|
||||
|
||||
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
|
||||
EXPECT_EQ(expected_identifier_string, identifier_string);
|
||||
}
|
||||
|
||||
// Test that a build id note with more bytes than usual is handled.
|
||||
TYPED_TEST(FileIDTest, BuildIDLong) {
|
||||
const uint8_t kExpectedIdentifierBytes[] =
|
||||
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
|
||||
const string expected_identifier_string =
|
||||
this->get_file_id(kExpectedIdentifierBytes);
|
||||
|
||||
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
Section text(kLittleEndian);
|
||||
text.Append(4096, 0);
|
||||
elf.AddSection(".text", text, SHT_PROGBITS);
|
||||
Notes notes(kLittleEndian);
|
||||
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
|
||||
sizeof(kExpectedIdentifierBytes));
|
||||
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
|
||||
elf.Finish();
|
||||
this->GetElfContents(elf);
|
||||
|
||||
id_vector identifier(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier));
|
||||
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
|
||||
|
||||
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
|
||||
EXPECT_EQ(expected_identifier_string, identifier_string);
|
||||
}
|
||||
|
||||
TYPED_TEST(FileIDTest, BuildIDPH) {
|
||||
const uint8_t kExpectedIdentifier[sizeof(MDGUID)] =
|
||||
const uint8_t kExpectedIdentifierBytes[] =
|
||||
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
|
||||
char expected_identifier_string[] =
|
||||
"00000000-0000-0000-0000-000000000000";
|
||||
FileID::ConvertIdentifierToString(kExpectedIdentifier,
|
||||
expected_identifier_string,
|
||||
sizeof(expected_identifier_string));
|
||||
|
||||
uint8_t identifier[sizeof(MDGUID)];
|
||||
char identifier_string[sizeof(expected_identifier_string)];
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13};
|
||||
const string expected_identifier_string =
|
||||
this->get_file_id(kExpectedIdentifierBytes);
|
||||
|
||||
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
Section text(kLittleEndian);
|
||||
@ -200,31 +262,25 @@ TYPED_TEST(FileIDTest, BuildIDPH) {
|
||||
Notes notes(kLittleEndian);
|
||||
notes.AddNote(0, "Linux",
|
||||
reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4);
|
||||
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier,
|
||||
sizeof(kExpectedIdentifier));
|
||||
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
|
||||
sizeof(kExpectedIdentifierBytes));
|
||||
int note_idx = elf.AddSection(".note", notes, SHT_NOTE);
|
||||
elf.AddSegment(note_idx, note_idx, PT_NOTE);
|
||||
elf.Finish();
|
||||
this->GetElfContents(elf);
|
||||
|
||||
id_vector identifier(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier));
|
||||
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
|
||||
|
||||
FileID::ConvertIdentifierToString(identifier, identifier_string,
|
||||
sizeof(identifier_string));
|
||||
EXPECT_STREQ(expected_identifier_string, identifier_string);
|
||||
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
|
||||
EXPECT_EQ(expected_identifier_string, identifier_string);
|
||||
}
|
||||
|
||||
// Test to make sure two files with different text sections produce
|
||||
// different hashes when not using a build id.
|
||||
TYPED_TEST(FileIDTest, UniqueHashes) {
|
||||
char identifier_string_1[] =
|
||||
"00000000-0000-0000-0000-000000000000";
|
||||
char identifier_string_2[] =
|
||||
"00000000-0000-0000-0000-000000000000";
|
||||
uint8_t identifier_1[sizeof(MDGUID)];
|
||||
uint8_t identifier_2[sizeof(MDGUID)];
|
||||
|
||||
{
|
||||
ELF elf1(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
Section foo_1(kLittleEndian);
|
||||
@ -237,10 +293,11 @@ TYPED_TEST(FileIDTest, UniqueHashes) {
|
||||
this->GetElfContents(elf1);
|
||||
}
|
||||
|
||||
id_vector identifier_1(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier_1));
|
||||
FileID::ConvertIdentifierToString(identifier_1, identifier_string_1,
|
||||
sizeof(identifier_string_1));
|
||||
string identifier_string_1 =
|
||||
FileID::ConvertIdentifierToUUIDString(identifier_1);
|
||||
|
||||
{
|
||||
ELF elf2(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
@ -254,10 +311,11 @@ TYPED_TEST(FileIDTest, UniqueHashes) {
|
||||
this->GetElfContents(elf2);
|
||||
}
|
||||
|
||||
id_vector identifier_2(this->make_vector());
|
||||
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
|
||||
identifier_2));
|
||||
FileID::ConvertIdentifierToString(identifier_2, identifier_string_2,
|
||||
sizeof(identifier_string_2));
|
||||
string identifier_string_2 =
|
||||
FileID::ConvertIdentifierToUUIDString(identifier_2);
|
||||
|
||||
EXPECT_STRNE(identifier_string_1, identifier_string_2);
|
||||
EXPECT_NE(identifier_string_1, identifier_string_2);
|
||||
}
|
||||
|
@ -72,7 +72,9 @@ bool HTTPUpload::SendRequest(const string &url,
|
||||
// We may have been linked statically; if curl_easy_init is in the
|
||||
// current binary, no need to search for a dynamic version.
|
||||
void* curl_lib = dlopen(NULL, RTLD_NOW);
|
||||
if (!curl_lib || dlsym(curl_lib, "curl_easy_init") == NULL) {
|
||||
if (!CheckCurlLib(curl_lib)) {
|
||||
fprintf(stderr,
|
||||
"Failed to open curl lib from binary, use libcurl.so instead\n");
|
||||
dlerror(); // Clear dlerror before attempting to open libraries.
|
||||
dlclose(curl_lib);
|
||||
curl_lib = NULL;
|
||||
@ -113,6 +115,10 @@ bool HTTPUpload::SendRequest(const string &url,
|
||||
*(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt");
|
||||
(*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str());
|
||||
(*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent);
|
||||
// Support multithread by disabling timeout handling, would get SIGSEGV with
|
||||
// Curl_resolv_timeout in stack trace otherwise.
|
||||
// See https://curl.haxx.se/libcurl/c/threadsafe.html
|
||||
(*curl_easy_setopt)(curl, CURLOPT_NOSIGNAL, 1);
|
||||
// Set proxy information if necessary.
|
||||
if (!proxy.empty())
|
||||
(*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str());
|
||||
@ -197,6 +203,13 @@ bool HTTPUpload::SendRequest(const string &url,
|
||||
return err_code == CURLE_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
bool HTTPUpload::CheckCurlLib(void* curl_lib) {
|
||||
return curl_lib &&
|
||||
dlsym(curl_lib, "curl_easy_init") &&
|
||||
dlsym(curl_lib, "curl_easy_setopt");
|
||||
}
|
||||
|
||||
// static
|
||||
bool HTTPUpload::CheckParameters(const map<string, string> ¶meters) {
|
||||
for (map<string, string>::const_iterator pos = parameters.begin();
|
||||
|
@ -74,6 +74,9 @@ class HTTPUpload {
|
||||
// any quote (") characters. Returns true if so.
|
||||
static bool CheckParameters(const map<string, string> ¶meters);
|
||||
|
||||
// Checks the curl_lib parameter points to a valid curl lib.
|
||||
static bool CheckCurlLib(void* curl_lib);
|
||||
|
||||
// No instances of this class should be created.
|
||||
// Disallow all constructors, destructors, and operator=.
|
||||
HTTPUpload();
|
||||
|
@ -35,6 +35,6 @@
|
||||
// the call fails, IGNORE_RET() can be used to mark the return code as ignored.
|
||||
// This avoids spurious compiler warnings.
|
||||
|
||||
#define IGNORE_RET(x) do { if (x); } while (0)
|
||||
#define IGNORE_RET(x) do { if (x) {} } while (0)
|
||||
|
||||
#endif // COMMON_LINUX_IGNORE_RET_H_
|
||||
|
155
src/common/linux/symbol_upload.cc
Normal file
155
src/common/linux/symbol_upload.cc
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2011 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper
|
||||
// function for linux symbol upload tool.
|
||||
|
||||
#include "common/linux/http_upload.h"
|
||||
#include "common/linux/symbol_upload.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace google_breakpad {
|
||||
namespace sym_upload {
|
||||
|
||||
void TokenizeByChar(const string &source_string, int c,
|
||||
std::vector<string> *results) {
|
||||
assert(results);
|
||||
string::size_type cur_pos = 0, next_pos = 0;
|
||||
while ((next_pos = source_string.find(c, cur_pos)) != string::npos) {
|
||||
if (next_pos != cur_pos)
|
||||
results->push_back(source_string.substr(cur_pos, next_pos - cur_pos));
|
||||
cur_pos = next_pos + 1;
|
||||
}
|
||||
if (cur_pos < source_string.size() && next_pos != cur_pos)
|
||||
results->push_back(source_string.substr(cur_pos));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Parse out the module line which have 5 parts.
|
||||
// MODULE <os> <cpu> <uuid> <module-name>
|
||||
bool ModuleDataForSymbolFile(const string &file,
|
||||
std::vector<string> *module_parts) {
|
||||
assert(module_parts);
|
||||
const size_t kModulePartNumber = 5;
|
||||
FILE* fp = fopen(file.c_str(), "r");
|
||||
if (fp) {
|
||||
char buffer[1024];
|
||||
if (fgets(buffer, sizeof(buffer), fp)) {
|
||||
string line(buffer);
|
||||
string::size_type line_break_pos = line.find_first_of('\n');
|
||||
if (line_break_pos == string::npos) {
|
||||
assert(0 && "The file is invalid!");
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
line.resize(line_break_pos);
|
||||
const char kDelimiter = ' ';
|
||||
TokenizeByChar(line, kDelimiter, module_parts);
|
||||
if (module_parts->size() != kModulePartNumber)
|
||||
module_parts->clear();
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return module_parts->size() == kModulePartNumber;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
string CompactIdentifier(const string &uuid) {
|
||||
std::vector<string> components;
|
||||
TokenizeByChar(uuid, '-', &components);
|
||||
string result;
|
||||
for (size_t i = 0; i < components.size(); ++i)
|
||||
result += components[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Start(Options *options) {
|
||||
std::map<string, string> parameters;
|
||||
options->success = false;
|
||||
std::vector<string> module_parts;
|
||||
if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
|
||||
fprintf(stderr, "Failed to parse symbol file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
string compacted_id = CompactIdentifier(module_parts[3]);
|
||||
|
||||
// Add parameters
|
||||
if (!options->version.empty())
|
||||
parameters["version"] = options->version;
|
||||
|
||||
// MODULE <os> <cpu> <uuid> <module-name>
|
||||
// 0 1 2 3 4
|
||||
parameters["os"] = module_parts[1];
|
||||
parameters["cpu"] = module_parts[2];
|
||||
parameters["debug_file"] = module_parts[4];
|
||||
parameters["code_file"] = module_parts[4];
|
||||
parameters["debug_identifier"] = compacted_id;
|
||||
|
||||
std::map<string, string> files;
|
||||
files["symbol_file"] = options->symbolsPath;
|
||||
|
||||
string response, error;
|
||||
long response_code;
|
||||
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
|
||||
parameters,
|
||||
files,
|
||||
options->proxy,
|
||||
options->proxy_user_pwd,
|
||||
"",
|
||||
&response,
|
||||
&response_code,
|
||||
&error);
|
||||
|
||||
if (!success) {
|
||||
printf("Failed to send symbol file: %s\n", error.c_str());
|
||||
printf("Response code: %ld\n", response_code);
|
||||
printf("Response:\n");
|
||||
printf("%s\n", response.c_str());
|
||||
} else if (response_code == 0) {
|
||||
printf("Failed to send symbol file: No response code\n");
|
||||
} else if (response_code != 200) {
|
||||
printf("Failed to send symbol file: Response code %ld\n", response_code);
|
||||
printf("Response:\n");
|
||||
printf("%s\n", response.c_str());
|
||||
} else {
|
||||
printf("Successfully sent the symbol file.\n");
|
||||
}
|
||||
options->success = success;
|
||||
}
|
||||
|
||||
} // namespace sym_upload
|
||||
} // namespace google_breakpad
|
59
src/common/linux/symbol_upload.h
Normal file
59
src/common/linux/symbol_upload.h
Normal file
@ -0,0 +1,59 @@
|
||||
// -*- mode: c++ -*-
|
||||
|
||||
// Copyright (c) 2011 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// symbol_upload.h: helper functions for linux symbol upload tool.
|
||||
|
||||
#ifndef COMMON_LINUX_SYMBOL_UPLOAD_H_
|
||||
#define COMMON_LINUX_SYMBOL_UPLOAD_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/using_std_string.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
namespace sym_upload {
|
||||
|
||||
typedef struct {
|
||||
string symbolsPath;
|
||||
string uploadURLStr;
|
||||
string proxy;
|
||||
string proxy_user_pwd;
|
||||
string version;
|
||||
bool success;
|
||||
} Options;
|
||||
|
||||
// Starts upload to symbol server with options.
|
||||
void Start(Options* options);
|
||||
|
||||
} // namespace sym_upload
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_SYMBOL_UPLOAD_H_
|
@ -27,12 +27,6 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
ARCHS = $(ARCHS_STANDARD_32_64_BIT)
|
||||
SDKROOT = macosx10.5
|
||||
|
||||
GCC_VERSION = 4.2
|
||||
GCC_VERSION[sdk=macosx10.4][arch=*] = 4.0
|
||||
|
||||
GCC_C_LANGUAGE_STANDARD = c99
|
||||
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES
|
||||
@ -41,7 +35,10 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = NO
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES
|
||||
GCC_WARN_MISSING_PARENTHESES = YES
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
|
||||
|
||||
// Once https://bugs.chromium.org/p/google-breakpad/issues/detail?id=697
|
||||
// is fixed this should be reenabled.
|
||||
//GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES
|
||||
GCC_WARN_SIGN_COMPARE = YES
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES
|
||||
@ -51,6 +48,5 @@ GCC_WARN_UNUSED_VARIABLE = YES
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES
|
||||
|
||||
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
|
||||
DEBUG_INFORMATION_FORMAT[sdk=macosx10.4][arch=*] = stabs
|
||||
|
||||
ALWAYS_SEARCH_USER_PATHS = NO
|
||||
|
@ -328,6 +328,65 @@ class DumpSymbols::DumperLineToModule:
|
||||
dwarf2reader::ByteReader *byte_reader_; // WEAK
|
||||
};
|
||||
|
||||
bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
|
||||
// Select an object file, if SetArchitecture hasn't been called to set one
|
||||
// explicitly.
|
||||
if (!selected_object_file_) {
|
||||
// If there's only one architecture, that's the one.
|
||||
if (object_files_.size() == 1)
|
||||
selected_object_file_ = &object_files_[0];
|
||||
else {
|
||||
// Look for an object file whose architecture matches our own.
|
||||
const NXArchInfo *local_arch = NXGetLocalArchInfo();
|
||||
if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
|
||||
fprintf(stderr, "%s: object file contains more than one"
|
||||
" architecture, none of which match the current"
|
||||
" architecture; specify an architecture explicitly"
|
||||
" with '-a ARCH' to resolve the ambiguity\n",
|
||||
object_filename_.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(selected_object_file_);
|
||||
|
||||
// Find the name of the selected file's architecture, to appear in
|
||||
// the MODULE record and in error messages.
|
||||
const NXArchInfo *selected_arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromCpuType(
|
||||
selected_object_file_->cputype, selected_object_file_->cpusubtype);
|
||||
|
||||
const char *selected_arch_name = selected_arch_info->name;
|
||||
if (strcmp(selected_arch_name, "i386") == 0)
|
||||
selected_arch_name = "x86";
|
||||
|
||||
// Produce a name to use in error messages that includes the
|
||||
// filename, and the architecture, if there is more than one.
|
||||
selected_object_name_ = object_filename_;
|
||||
if (object_files_.size() > 1) {
|
||||
selected_object_name_ += ", architecture ";
|
||||
selected_object_name_ + selected_arch_name;
|
||||
}
|
||||
|
||||
// Compute a module name, to appear in the MODULE record.
|
||||
string module_name = object_filename_;
|
||||
module_name = basename(&module_name[0]);
|
||||
|
||||
// Choose an identifier string, to appear in the MODULE record.
|
||||
string identifier = Identifier();
|
||||
if (identifier.empty())
|
||||
return false;
|
||||
identifier += "0";
|
||||
|
||||
// Create a module to hold the debugging information.
|
||||
module.reset(new Module(module_name,
|
||||
"mac",
|
||||
selected_arch_name,
|
||||
identifier));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
|
||||
const mach_o::Reader &macho_reader,
|
||||
const mach_o::SectionMap &dwarf_sections,
|
||||
@ -378,7 +437,8 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
|
||||
// Make a Dwarf2Handler that drives our DIEHandler.
|
||||
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
|
||||
// Make a DWARF parser for the compilation unit at OFFSET.
|
||||
dwarf2reader::CompilationUnit dwarf_reader(file_context.section_map(),
|
||||
dwarf2reader::CompilationUnit dwarf_reader(selected_object_name_,
|
||||
file_context.section_map(),
|
||||
offset,
|
||||
&byte_reader,
|
||||
&die_dispatcher);
|
||||
@ -535,61 +595,9 @@ bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer &entries,
|
||||
}
|
||||
|
||||
bool DumpSymbols::ReadSymbolData(Module** out_module) {
|
||||
// Select an object file, if SetArchitecture hasn't been called to set one
|
||||
// explicitly.
|
||||
if (!selected_object_file_) {
|
||||
// If there's only one architecture, that's the one.
|
||||
if (object_files_.size() == 1)
|
||||
selected_object_file_ = &object_files_[0];
|
||||
else {
|
||||
// Look for an object file whose architecture matches our own.
|
||||
const NXArchInfo *local_arch = NXGetLocalArchInfo();
|
||||
if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
|
||||
fprintf(stderr, "%s: object file contains more than one"
|
||||
" architecture, none of which match the current"
|
||||
" architecture; specify an architecture explicitly"
|
||||
" with '-a ARCH' to resolve the ambiguity\n",
|
||||
object_filename_.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(selected_object_file_);
|
||||
|
||||
// Find the name of the selected file's architecture, to appear in
|
||||
// the MODULE record and in error messages.
|
||||
const NXArchInfo *selected_arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromCpuType(
|
||||
selected_object_file_->cputype, selected_object_file_->cpusubtype);
|
||||
|
||||
const char *selected_arch_name = selected_arch_info->name;
|
||||
if (strcmp(selected_arch_name, "i386") == 0)
|
||||
selected_arch_name = "x86";
|
||||
|
||||
// Produce a name to use in error messages that includes the
|
||||
// filename, and the architecture, if there is more than one.
|
||||
selected_object_name_ = object_filename_;
|
||||
if (object_files_.size() > 1) {
|
||||
selected_object_name_ += ", architecture ";
|
||||
selected_object_name_ + selected_arch_name;
|
||||
}
|
||||
|
||||
// Compute a module name, to appear in the MODULE record.
|
||||
string module_name = object_filename_;
|
||||
module_name = basename(&module_name[0]);
|
||||
|
||||
// Choose an identifier string, to appear in the MODULE record.
|
||||
string identifier = Identifier();
|
||||
if (identifier.empty())
|
||||
scoped_ptr<Module> module;
|
||||
if (!CreateEmptyModule(module))
|
||||
return false;
|
||||
identifier += "0";
|
||||
|
||||
// Create a module to hold the debugging information.
|
||||
scoped_ptr<Module> module(new Module(module_name,
|
||||
"mac",
|
||||
selected_arch_name,
|
||||
identifier));
|
||||
|
||||
// Parse the selected object file.
|
||||
mach_o::Reader::Reporter reporter(selected_object_name_);
|
||||
@ -624,4 +632,15 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the selected object file's debugging information, and write out the
|
||||
// header only to |stream|. Return true on success; if an error occurs, report
|
||||
// it and return false.
|
||||
bool DumpSymbols::WriteSymbolFileHeader(std::ostream &stream) {
|
||||
scoped_ptr<Module> module;
|
||||
if (!CreateEmptyModule(module))
|
||||
return false;
|
||||
|
||||
return module->Write(stream, symbol_data_);
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -112,6 +112,11 @@ class DumpSymbols {
|
||||
// return false.
|
||||
bool WriteSymbolFile(std::ostream &stream);
|
||||
|
||||
// Read the selected object file's debugging information, and write out the
|
||||
// header only to |stream|. Return true on success; if an error occurs, report
|
||||
// it and return false.
|
||||
bool WriteSymbolFileHeader(std::ostream &stream);
|
||||
|
||||
// As above, but simply return the debugging information in module
|
||||
// instead of writing it to a stream. The caller owns the resulting
|
||||
// module object and must delete it when finished.
|
||||
@ -130,6 +135,10 @@ class DumpSymbols {
|
||||
// Return an identifier string for the file this DumpSymbols is dumping.
|
||||
std::string Identifier();
|
||||
|
||||
|
||||
// Creates an empty module object.
|
||||
bool CreateEmptyModule(scoped_ptr<Module>& module);
|
||||
|
||||
// Read debugging information from |dwarf_sections|, which was taken from
|
||||
// |macho_reader|, and add it to |module|. On success, return true;
|
||||
// on failure, report the problem and return false.
|
||||
|
@ -181,15 +181,15 @@ void Reader::Reporter::LoadCommandRegionTruncated() {
|
||||
|
||||
void Reader::Reporter::LoadCommandsOverrun(size_t claimed, size_t i,
|
||||
LoadCommandType type) {
|
||||
fprintf(stderr, "%s: file's header claims there are %ld"
|
||||
" load commands, but load command #%ld",
|
||||
fprintf(stderr, "%s: file's header claims there are %zu"
|
||||
" load commands, but load command #%zu",
|
||||
filename_.c_str(), claimed, i);
|
||||
if (type) fprintf(stderr, ", of type %d,", type);
|
||||
fprintf(stderr, " extends beyond the end of the load command region\n");
|
||||
}
|
||||
|
||||
void Reader::Reporter::LoadCommandTooShort(size_t i, LoadCommandType type) {
|
||||
fprintf(stderr, "%s: the contents of load command #%ld, of type %d,"
|
||||
fprintf(stderr, "%s: the contents of load command #%zu, of type %d,"
|
||||
" extend beyond the size given in the load command's header\n",
|
||||
filename_.c_str(), i, type);
|
||||
}
|
||||
|
@ -26,10 +26,6 @@
|
||||
#import "GTMObjC2Runtime.h"
|
||||
#import "GTMUnitTestDevLog.h"
|
||||
|
||||
#if !GTM_IPHONE_SDK
|
||||
#import "GTMGarbageCollection.h"
|
||||
#endif // !GTM_IPHONE_SDK
|
||||
|
||||
#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
|
||||
#import <stdarg.h>
|
||||
|
||||
@ -430,71 +426,3 @@ static int MethodSort(id a, id b, void *context) {
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Leak detection
|
||||
#if !GTM_IPHONE_DEVICE && !GTM_SUPPRESS_RUN_LEAKS_HOOK
|
||||
// Don't want to get leaks on the iPhone Device as the device doesn't
|
||||
// have 'leaks'. The simulator does though.
|
||||
|
||||
// COV_NF_START
|
||||
// We don't have leak checking on by default, so this won't be hit.
|
||||
static void _GTMRunLeaks(void) {
|
||||
// This is an atexit handler. It runs leaks for us to check if we are
|
||||
// leaking anything in our tests.
|
||||
const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE");
|
||||
NSMutableString *exclusions = [NSMutableString string];
|
||||
if (cExclusionsEnv) {
|
||||
NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv];
|
||||
NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","];
|
||||
NSString *exclusion;
|
||||
NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet];
|
||||
GTM_FOREACH_OBJECT(exclusion, exclusionsArray) {
|
||||
exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet];
|
||||
[exclusions appendFormat:@"-exclude \"%@\" ", exclusion];
|
||||
}
|
||||
}
|
||||
// Clearing out DYLD_ROOT_PATH because iPhone Simulator framework libraries
|
||||
// are different from regular OS X libraries and leaks will fail to run
|
||||
// because of missing symbols. Also capturing the output of leaks and then
|
||||
// pipe rather than a direct pipe, because otherwise if leaks failed,
|
||||
// the system() call will still be successful. Bug:
|
||||
// http://code.google.com/p/google-toolbox-for-mac/issues/detail?id=56
|
||||
NSString *string
|
||||
= [NSString stringWithFormat:
|
||||
@"LeakOut=`DYLD_ROOT_PATH='' /usr/bin/leaks %@%d` &&"
|
||||
@"echo \"$LeakOut\"|/usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'",
|
||||
exclusions, getpid()];
|
||||
int ret = system([string UTF8String]);
|
||||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"%s:%d: Error: Unable to run leaks. 'system' returned: %d\n",
|
||||
__FILE__, __LINE__, ret);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
// COV_NF_END
|
||||
|
||||
static __attribute__((constructor)) void _GTMInstallLeaks(void) {
|
||||
BOOL checkLeaks = YES;
|
||||
#if !GTM_IPHONE_SDK
|
||||
checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES;
|
||||
#endif // !GTM_IPHONE_SDK
|
||||
if (checkLeaks) {
|
||||
checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO;
|
||||
if (checkLeaks) {
|
||||
// COV_NF_START
|
||||
// We don't have leak checking on by default, so this won't be hit.
|
||||
fprintf(stderr, "Leak Checking Enabled\n");
|
||||
fflush(stderr);
|
||||
int ret = atexit(&_GTMRunLeaks);
|
||||
// To avoid unused variable warning when _GTMDevAssert is stripped.
|
||||
(void)ret;
|
||||
_GTMDevAssert(ret == 0,
|
||||
@"Unable to install _GTMRunLeaks as an atexit handler (%d)",
|
||||
errno);
|
||||
// COV_NF_END
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !GTM_IPHONE_DEVICE && !GTM_SUPPRESS_RUN_LEAKS_HOOK
|
||||
|
@ -64,7 +64,8 @@ class PageAllocator {
|
||||
: page_size_(getpagesize()),
|
||||
last_(NULL),
|
||||
current_page_(NULL),
|
||||
page_offset_(0) {
|
||||
page_offset_(0),
|
||||
pages_allocated_(0) {
|
||||
}
|
||||
|
||||
~PageAllocator() {
|
||||
@ -112,6 +113,8 @@ class PageAllocator {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long pages_allocated() { return pages_allocated_; }
|
||||
|
||||
private:
|
||||
uint8_t *GetNPages(size_t num_pages) {
|
||||
#if defined(__x86_64__) || defined(__aarch64__) || defined(__aarch64__) || \
|
||||
@ -136,6 +139,8 @@ class PageAllocator {
|
||||
header->num_pages = num_pages;
|
||||
last_ = header;
|
||||
|
||||
pages_allocated_ += num_pages;
|
||||
|
||||
return reinterpret_cast<uint8_t*>(a);
|
||||
}
|
||||
|
||||
@ -157,6 +162,7 @@ class PageAllocator {
|
||||
PageHeader *last_;
|
||||
uint8_t *current_page_;
|
||||
size_t page_offset_;
|
||||
unsigned long pages_allocated_;
|
||||
};
|
||||
|
||||
// Wrapper to use with STL containers
|
||||
@ -165,12 +171,30 @@ struct PageStdAllocator : public std::allocator<T> {
|
||||
typedef typename std::allocator<T>::pointer pointer;
|
||||
typedef typename std::allocator<T>::size_type size_type;
|
||||
|
||||
explicit PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {}
|
||||
explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator),
|
||||
stackdata_(NULL),
|
||||
stackdata_size_(0)
|
||||
{}
|
||||
|
||||
template <class Other> PageStdAllocator(const PageStdAllocator<Other>& other)
|
||||
: allocator_(other.allocator_) {}
|
||||
: allocator_(other.allocator_),
|
||||
stackdata_(nullptr),
|
||||
stackdata_size_(0)
|
||||
{}
|
||||
|
||||
explicit PageStdAllocator(PageAllocator& allocator,
|
||||
pointer stackdata,
|
||||
size_type stackdata_size) : allocator_(allocator),
|
||||
stackdata_(stackdata),
|
||||
stackdata_size_(stackdata_size)
|
||||
{}
|
||||
|
||||
inline pointer allocate(size_type n, const void* = 0) {
|
||||
return static_cast<pointer>(allocator_.Alloc(sizeof(T) * n));
|
||||
const size_type size = sizeof(T) * n;
|
||||
if (size <= stackdata_size_) {
|
||||
return stackdata_;
|
||||
}
|
||||
return static_cast<pointer>(allocator_.Alloc(size));
|
||||
}
|
||||
|
||||
inline void deallocate(pointer, size_type) {
|
||||
@ -188,6 +212,8 @@ struct PageStdAllocator : public std::allocator<T> {
|
||||
template<typename Other> friend struct PageStdAllocator;
|
||||
|
||||
PageAllocator& allocator_;
|
||||
pointer stackdata_;
|
||||
size_type stackdata_size_;
|
||||
};
|
||||
|
||||
// A wasteful vector is a std::vector, except that it allocates memory from a
|
||||
@ -200,6 +226,24 @@ class wasteful_vector : public std::vector<T, PageStdAllocator<T> > {
|
||||
: std::vector<T, PageStdAllocator<T> >(PageStdAllocator<T>(*allocator)) {
|
||||
std::vector<T, PageStdAllocator<T> >::reserve(size_hint);
|
||||
}
|
||||
protected:
|
||||
wasteful_vector(PageStdAllocator<T> allocator)
|
||||
: std::vector<T, PageStdAllocator<T> >(allocator) {}
|
||||
};
|
||||
|
||||
// auto_wasteful_vector allocates space on the stack for N entries to avoid
|
||||
// using the PageAllocator for small data, while still allowing for larger data.
|
||||
template<class T, unsigned int N>
|
||||
class auto_wasteful_vector : public wasteful_vector<T> {
|
||||
T stackdata_[N];
|
||||
public:
|
||||
auto_wasteful_vector(PageAllocator* allocator)
|
||||
: wasteful_vector<T>(
|
||||
PageStdAllocator<T>(*allocator,
|
||||
&stackdata_[0],
|
||||
sizeof(stackdata_))) {
|
||||
std::vector<T, PageStdAllocator<T> >::reserve(N);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -38,11 +38,13 @@ typedef testing::Test PageAllocatorTest;
|
||||
|
||||
TEST(PageAllocatorTest, Setup) {
|
||||
PageAllocator allocator;
|
||||
EXPECT_EQ(0U, allocator.pages_allocated());
|
||||
}
|
||||
|
||||
TEST(PageAllocatorTest, SmallObjects) {
|
||||
PageAllocator allocator;
|
||||
|
||||
EXPECT_EQ(0U, allocator.pages_allocated());
|
||||
for (unsigned i = 1; i < 1024; ++i) {
|
||||
uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
|
||||
ASSERT_FALSE(p == NULL);
|
||||
@ -53,8 +55,10 @@ TEST(PageAllocatorTest, SmallObjects) {
|
||||
TEST(PageAllocatorTest, LargeObject) {
|
||||
PageAllocator allocator;
|
||||
|
||||
EXPECT_EQ(0U, allocator.pages_allocated());
|
||||
uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
|
||||
ASSERT_FALSE(p == NULL);
|
||||
EXPECT_EQ(3U, allocator.pages_allocated());
|
||||
for (unsigned i = 1; i < 10; ++i) {
|
||||
uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
|
||||
ASSERT_FALSE(p == NULL);
|
||||
@ -75,6 +79,7 @@ TEST(WastefulVectorTest, Setup) {
|
||||
|
||||
TEST(WastefulVectorTest, Simple) {
|
||||
PageAllocator allocator_;
|
||||
EXPECT_EQ(0U, allocator_.pages_allocated());
|
||||
wasteful_vector<unsigned> v(&allocator_);
|
||||
|
||||
for (unsigned i = 0; i < 256; ++i) {
|
||||
@ -84,6 +89,7 @@ TEST(WastefulVectorTest, Simple) {
|
||||
}
|
||||
ASSERT_FALSE(v.empty());
|
||||
ASSERT_EQ(v.size(), 256u);
|
||||
EXPECT_EQ(1U, allocator_.pages_allocated());
|
||||
for (unsigned i = 0; i < 256; ++i)
|
||||
ASSERT_EQ(v[i], i);
|
||||
}
|
||||
@ -91,7 +97,28 @@ TEST(WastefulVectorTest, Simple) {
|
||||
TEST(WastefulVectorTest, UsesPageAllocator) {
|
||||
PageAllocator allocator_;
|
||||
wasteful_vector<unsigned> v(&allocator_);
|
||||
EXPECT_EQ(1U, allocator_.pages_allocated());
|
||||
|
||||
v.push_back(1);
|
||||
ASSERT_TRUE(allocator_.OwnsPointer(&v[0]));
|
||||
}
|
||||
|
||||
TEST(WastefulVectorTest, AutoWastefulVector) {
|
||||
PageAllocator allocator_;
|
||||
EXPECT_EQ(0U, allocator_.pages_allocated());
|
||||
|
||||
auto_wasteful_vector<unsigned, 4> v(&allocator_);
|
||||
EXPECT_EQ(0U, allocator_.pages_allocated());
|
||||
|
||||
v.push_back(1);
|
||||
EXPECT_EQ(0U, allocator_.pages_allocated());
|
||||
EXPECT_FALSE(allocator_.OwnsPointer(&v[0]));
|
||||
|
||||
v.resize(4);
|
||||
EXPECT_EQ(0U, allocator_.pages_allocated());
|
||||
EXPECT_FALSE(allocator_.OwnsPointer(&v[0]));
|
||||
|
||||
v.resize(10);
|
||||
EXPECT_EQ(1U, allocator_.pages_allocated());
|
||||
EXPECT_TRUE(allocator_.OwnsPointer(&v[0]));
|
||||
}
|
||||
|
@ -27,8 +27,8 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_STDIO_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_STDIO_H
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -40,4 +40,4 @@ typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_STDIO_H
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
|
@ -210,7 +210,7 @@ bool FindAndLoadOmapTable(const wchar_t* name,
|
||||
reinterpret_cast<BYTE*>(&table->at(0)),
|
||||
&count_read))) {
|
||||
fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
|
||||
"data from stream \"%ws\"\n");
|
||||
"data from stream \"%ws\"\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -975,6 +975,16 @@ bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function,
|
||||
fprintf(stderr, "failed to get function name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's possible for get_name to return an empty string, so
|
||||
// special-case that.
|
||||
if (wcscmp(*name, L"") == 0) {
|
||||
SysFreeString(*name);
|
||||
// dwarf_cu_to_module.cc uses "<name omitted>", so match that.
|
||||
*name = SysAllocString(L"<name omitted>");
|
||||
return true;
|
||||
}
|
||||
|
||||
// If a name comes from get_name because no undecorated form existed,
|
||||
// it's already formatted properly to be used as output. Don't do any
|
||||
// additional processing.
|
||||
|
@ -3,6 +3,9 @@
|
||||
/* Define to 1 if you have the <a.out.h> header file. */
|
||||
#undef HAVE_A_OUT_H
|
||||
|
||||
/* define if the compiler supports basic C++11 syntax */
|
||||
#undef HAVE_CXX11
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
|
@ -328,6 +328,10 @@ typedef enum {
|
||||
MD_MEMORY_INFO_LIST_STREAM = 16, /* MDRawMemoryInfoList */
|
||||
MD_THREAD_INFO_LIST_STREAM = 17,
|
||||
MD_HANDLE_OPERATION_LIST_STREAM = 18,
|
||||
MD_TOKEN_STREAM = 19,
|
||||
MD_JAVASCRIPT_DATA_STREAM = 20,
|
||||
MD_SYSTEM_MEMORY_INFO_STREAM = 21,
|
||||
MD_PROCESS_VM_COUNTERS_STREAM = 22,
|
||||
MD_LAST_RESERVED_STREAM = 0x0000ffff,
|
||||
|
||||
/* Breakpad extension types. 0x4767 = "Gg" */
|
||||
|
@ -45,6 +45,7 @@
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace google_breakpad {
|
||||
@ -61,15 +62,24 @@ class CallStack {
|
||||
|
||||
// Resets the CallStack to its initial empty state
|
||||
void Clear();
|
||||
|
||||
|
||||
const vector<StackFrame*>* frames() const { return &frames_; }
|
||||
|
||||
// Set the TID associated with this call stack.
|
||||
void set_tid(uint32_t tid) { tid_ = tid; }
|
||||
|
||||
uint32_t tid() const { return tid_; }
|
||||
|
||||
private:
|
||||
// Stackwalker is responsible for building the frames_ vector.
|
||||
friend class Stackwalker;
|
||||
|
||||
// Storage for pushed frames.
|
||||
vector<StackFrame*> frames_;
|
||||
|
||||
// The TID associated with this call stack. Default to 0 if it's not
|
||||
// available.
|
||||
uint32_t tid_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -67,6 +67,8 @@ class MicrodumpContext : public DumpContext {
|
||||
virtual void SetContextARM(MDRawContextARM* arm);
|
||||
virtual void SetContextARM64(MDRawContextARM64* arm64);
|
||||
virtual void SetContextX86(MDRawContextX86* x86);
|
||||
virtual void SetContextMIPS(MDRawContextMIPS* mips32);
|
||||
virtual void SetContextMIPS64(MDRawContextMIPS* mips64);
|
||||
};
|
||||
|
||||
// This class provides access to microdump memory regions.
|
||||
|
@ -46,8 +46,7 @@
|
||||
namespace google_breakpad {
|
||||
|
||||
BasicCodeModules::BasicCodeModules(const CodeModules *that)
|
||||
: main_address_(0),
|
||||
map_(new RangeMap<uint64_t, linked_ptr<const CodeModule> >()) {
|
||||
: main_address_(0), map_() {
|
||||
BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires "
|
||||
"|that|";
|
||||
assert(that);
|
||||
@ -66,30 +65,27 @@ BasicCodeModules::BasicCodeModules(const CodeModules *that)
|
||||
// GetModuleAtSequence.
|
||||
linked_ptr<const CodeModule> module(
|
||||
that->GetModuleAtIndex(module_sequence)->Copy());
|
||||
if (!map_->StoreRange(module->base_address(), module->size(), module)) {
|
||||
if (!map_.StoreRange(module->base_address(), module->size(), module)) {
|
||||
BPLOG(ERROR) << "Module " << module->code_file() <<
|
||||
" could not be stored";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicCodeModules::BasicCodeModules()
|
||||
: main_address_(0),
|
||||
map_(new RangeMap<uint64_t, linked_ptr<const CodeModule> >()) {
|
||||
}
|
||||
BasicCodeModules::BasicCodeModules() : main_address_(0), map_() { }
|
||||
|
||||
BasicCodeModules::~BasicCodeModules() {
|
||||
delete map_;
|
||||
}
|
||||
|
||||
unsigned int BasicCodeModules::module_count() const {
|
||||
return map_->GetCount();
|
||||
return map_.GetCount();
|
||||
}
|
||||
|
||||
const CodeModule* BasicCodeModules::GetModuleForAddress(
|
||||
uint64_t address) const {
|
||||
linked_ptr<const CodeModule> module;
|
||||
if (!map_->RetrieveRange(address, &module, NULL, NULL)) {
|
||||
if (!map_.RetrieveRange(address, &module, NULL /* base */, NULL /* delta */,
|
||||
NULL /* size */)) {
|
||||
BPLOG(INFO) << "No module at " << HexString(address);
|
||||
return NULL;
|
||||
}
|
||||
@ -104,7 +100,8 @@ const CodeModule* BasicCodeModules::GetMainModule() const {
|
||||
const CodeModule* BasicCodeModules::GetModuleAtSequence(
|
||||
unsigned int sequence) const {
|
||||
linked_ptr<const CodeModule> module;
|
||||
if (!map_->RetrieveRangeAtIndex(sequence, &module, NULL, NULL)) {
|
||||
if (!map_.RetrieveRangeAtIndex(sequence, &module, NULL /* base */,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
BPLOG(ERROR) << "RetrieveRangeAtIndex failed for sequence " << sequence;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -41,13 +41,14 @@
|
||||
#ifndef PROCESSOR_BASIC_CODE_MODULES_H__
|
||||
#define PROCESSOR_BASIC_CODE_MODULES_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/processor/code_modules.h"
|
||||
#include "processor/linked_ptr.h"
|
||||
#include "processor/range_map.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
template<typename T> class linked_ptr;
|
||||
template<typename AddressType, typename EntryType> class RangeMap;
|
||||
|
||||
class BasicCodeModules : public CodeModules {
|
||||
public:
|
||||
// Creates a new BasicCodeModules object given any existing CodeModules
|
||||
@ -75,7 +76,7 @@ class BasicCodeModules : public CodeModules {
|
||||
|
||||
// The map used to contain each CodeModule, keyed by each CodeModule's
|
||||
// address range.
|
||||
RangeMap<uint64_t, linked_ptr<const CodeModule> > *map_;
|
||||
RangeMap<uint64_t, linked_ptr<const CodeModule> > map_;
|
||||
|
||||
private:
|
||||
// Disallow copy constructor and assignment operator.
|
||||
|
@ -203,15 +203,16 @@ void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
|
||||
MemAddr function_base;
|
||||
MemAddr function_size;
|
||||
MemAddr public_address;
|
||||
if (functions_.RetrieveNearestRange(address, &func,
|
||||
&function_base, &function_size) &&
|
||||
if (functions_.RetrieveNearestRange(address, &func, &function_base,
|
||||
NULL /* delta */, &function_size) &&
|
||||
address >= function_base && address - function_base < function_size) {
|
||||
frame->function_name = func->name;
|
||||
frame->function_base = frame->module->base_address() + function_base;
|
||||
|
||||
linked_ptr<Line> line;
|
||||
MemAddr line_base;
|
||||
if (func->lines.RetrieveRange(address, &line, &line_base, NULL)) {
|
||||
if (func->lines.RetrieveRange(address, &line, &line_base, NULL /* delta */,
|
||||
NULL /* size */)) {
|
||||
FileMap::const_iterator it = files_.find(line->source_file_id);
|
||||
if (it != files_.end()) {
|
||||
frame->source_file_name = files_.find(line->source_file_id)->second;
|
||||
@ -256,8 +257,8 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
|
||||
// comparison in an overflow-friendly way.
|
||||
linked_ptr<Function> function;
|
||||
MemAddr function_base, function_size;
|
||||
if (functions_.RetrieveNearestRange(address, &function,
|
||||
&function_base, &function_size) &&
|
||||
if (functions_.RetrieveNearestRange(address, &function, &function_base,
|
||||
NULL /* delta */, &function_size) &&
|
||||
address >= function_base && address - function_base < function_size) {
|
||||
result->parameter_size = function->parameter_size;
|
||||
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
|
||||
@ -286,8 +287,8 @@ CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
|
||||
// provides an initial set of register recovery rules. Then, walk
|
||||
// forward from the initial rule's starting address to frame's
|
||||
// instruction address, applying delta rules.
|
||||
if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules,
|
||||
&initial_base, &initial_size)) {
|
||||
if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, &initial_base,
|
||||
NULL /* delta */, &initial_size)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -482,7 +483,7 @@ bool SymbolParseHelper::ParseFile(char *file_line, long *index,
|
||||
}
|
||||
|
||||
*filename = tokens[1];
|
||||
if (!filename) {
|
||||
if (!*filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -595,7 +596,7 @@ bool SymbolParseHelper::ParsePublicSymbol(char *public_line,
|
||||
*stack_param_size < 0) {
|
||||
return false;
|
||||
}
|
||||
*name = tokens[2];
|
||||
*name = tokens[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ void CallStack::Clear() {
|
||||
++iterator) {
|
||||
delete *iterator;
|
||||
}
|
||||
tid_ = 0;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -54,7 +54,7 @@ class MemoryRegion;
|
||||
// values, when the PC is at a given address in the current frame's
|
||||
// function. See the description of 'STACK CFI' records at:
|
||||
//
|
||||
// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
|
||||
// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
|
||||
//
|
||||
// To prepare an instance of CFIFrameInfo for use at a given
|
||||
// instruction, first populate it with the rules from the 'STACK CFI
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <unistd.h>
|
||||
#endif // _WIN32
|
||||
|
||||
#include "common/stdio.h"
|
||||
#include "common/stdio_wrapper.h"
|
||||
#include "processor/logging.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/stdio.h"
|
||||
#include "common/stdio_wrapper.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "processor/logging.h"
|
||||
#include "processor/pathname_stripper.h"
|
||||
|
@ -61,6 +61,8 @@ static const char kStackFirstLineKey[] = ": S 0 ";
|
||||
static const char kArmArchitecture[] = "arm";
|
||||
static const char kArm64Architecture[] = "arm64";
|
||||
static const char kX86Architecture[] = "x86";
|
||||
static const char kMipsArchitecture[] = "mips";
|
||||
static const char kMips64Architecture[] = "mips64";
|
||||
static const char kGpuUnknown[] = "UNKNOWN";
|
||||
|
||||
template<typename T>
|
||||
@ -102,7 +104,7 @@ namespace google_breakpad {
|
||||
|
||||
void MicrodumpModules::Add(const CodeModule* module) {
|
||||
linked_ptr<const CodeModule> module_ptr(module);
|
||||
if (!map_->StoreRange(module->base_address(), module->size(), module_ptr)) {
|
||||
if (!map_.StoreRange(module->base_address(), module->size(), module_ptr)) {
|
||||
BPLOG(ERROR) << "Module " << module->code_file() <<
|
||||
" could not be stored";
|
||||
}
|
||||
@ -131,6 +133,18 @@ void MicrodumpContext::SetContextX86(MDRawContextX86* x86) {
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
void MicrodumpContext::SetContextMIPS(MDRawContextMIPS* mips32) {
|
||||
DumpContext::SetContextFlags(MD_CONTEXT_MIPS);
|
||||
DumpContext::SetContextMIPS(mips32);
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
void MicrodumpContext::SetContextMIPS64(MDRawContextMIPS* mips64) {
|
||||
DumpContext::SetContextFlags(MD_CONTEXT_MIPS64);
|
||||
DumpContext::SetContextMIPS(mips64);
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// MicrodumpMemoryRegion
|
||||
@ -281,8 +295,9 @@ Microdump::Microdump(const string& contents)
|
||||
std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str);
|
||||
if (strcmp(arch.c_str(), kArmArchitecture) == 0) {
|
||||
if (cpu_state_raw.size() != sizeof(MDRawContextARM)) {
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
|
||||
" bytes instead of " << sizeof(MDRawContextARM) << std::endl;
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
|
||||
<< " bytes instead of " << sizeof(MDRawContextARM)
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
MDRawContextARM* arm = new MDRawContextARM();
|
||||
@ -290,8 +305,9 @@ Microdump::Microdump(const string& contents)
|
||||
context_->SetContextARM(arm);
|
||||
} else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
|
||||
if (cpu_state_raw.size() != sizeof(MDRawContextARM64)) {
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
|
||||
" bytes instead of " << sizeof(MDRawContextARM64) << std::endl;
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
|
||||
<< " bytes instead of " << sizeof(MDRawContextARM64)
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
MDRawContextARM64* arm = new MDRawContextARM64();
|
||||
@ -299,13 +315,34 @@ Microdump::Microdump(const string& contents)
|
||||
context_->SetContextARM64(arm);
|
||||
} else if (strcmp(arch.c_str(), kX86Architecture) == 0) {
|
||||
if (cpu_state_raw.size() != sizeof(MDRawContextX86)) {
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
|
||||
" bytes instead of " << sizeof(MDRawContextX86) << std::endl;
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
|
||||
<< " bytes instead of " << sizeof(MDRawContextX86)
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
MDRawContextX86* x86 = new MDRawContextX86();
|
||||
memcpy(x86, &cpu_state_raw[0], cpu_state_raw.size());
|
||||
context_->SetContextX86(x86);
|
||||
} else if (strcmp(arch.c_str(), kMipsArchitecture) == 0) {
|
||||
if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
|
||||
<< " bytes instead of " << sizeof(MDRawContextMIPS)
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
MDRawContextMIPS* mips32 = new MDRawContextMIPS();
|
||||
memcpy(mips32, &cpu_state_raw[0], cpu_state_raw.size());
|
||||
context_->SetContextMIPS(mips32);
|
||||
} else if (strcmp(arch.c_str(), kMips64Architecture) == 0) {
|
||||
if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
|
||||
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
|
||||
<< " bytes instead of " << sizeof(MDRawContextMIPS)
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
MDRawContextMIPS* mips64 = new MDRawContextMIPS();
|
||||
memcpy(mips64, &cpu_state_raw[0], cpu_state_raw.size());
|
||||
context_->SetContextMIPS64(mips64);
|
||||
} else {
|
||||
std::cerr << "Unsupported architecture: " << arch << std::endl;
|
||||
}
|
||||
|
@ -223,6 +223,48 @@ TEST_F(MicrodumpProcessorTest, TestProcessMultiple) {
|
||||
ASSERT_EQ(2U, state.threads()->at(0)->frames()->size());
|
||||
}
|
||||
|
||||
TEST_F(MicrodumpProcessorTest, TestProcessMips) {
|
||||
ProcessState state;
|
||||
AnalyzeDump("microdump-mips32.dmp", false /* omit_symbols */,
|
||||
2 /* expected_cpu_count */, &state);
|
||||
|
||||
ASSERT_EQ(7U, state.modules()->module_count());
|
||||
ASSERT_EQ("mips", state.system_info()->cpu);
|
||||
ASSERT_EQ("3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015",
|
||||
state.system_info()->os_version);
|
||||
ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
|
||||
|
||||
ASSERT_EQ("blaTest",
|
||||
state.threads()->at(0)->frames()->at(0)->function_name);
|
||||
ASSERT_EQ("Crash",
|
||||
state.threads()->at(0)->frames()->at(1)->function_name);
|
||||
ASSERT_EQ("main",
|
||||
state.threads()->at(0)->frames()->at(2)->function_name);
|
||||
ASSERT_EQ("crash_example",
|
||||
state.threads()->at(0)->frames()->at(0)->module->debug_file());
|
||||
}
|
||||
|
||||
TEST_F(MicrodumpProcessorTest, TestProcessMips64) {
|
||||
ProcessState state;
|
||||
AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
|
||||
1 /* expected_cpu_count */, &state);
|
||||
|
||||
ASSERT_EQ(7U, state.modules()->module_count());
|
||||
ASSERT_EQ("mips64", state.system_info()->cpu);
|
||||
ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
|
||||
state.system_info()->os_version);
|
||||
ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
|
||||
|
||||
ASSERT_EQ("blaTest",
|
||||
state.threads()->at(0)->frames()->at(0)->function_name);
|
||||
ASSERT_EQ("Crash",
|
||||
state.threads()->at(0)->frames()->at(1)->function_name);
|
||||
ASSERT_EQ("main",
|
||||
state.threads()->at(0)->frames()->at(2)->function_name);
|
||||
ASSERT_EQ("crash_example",
|
||||
state.threads()->at(0)->frames()->at(0)->module->debug_file());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
@ -57,7 +57,7 @@
|
||||
#include "processor/range_map-inl.h"
|
||||
|
||||
#include "common/scoped_ptr.h"
|
||||
#include "common/stdio.h"
|
||||
#include "common/stdio_wrapper.h"
|
||||
#include "google_breakpad/processor/dump_context.h"
|
||||
#include "processor/basic_code_module.h"
|
||||
#include "processor/basic_code_modules.h"
|
||||
@ -1180,7 +1180,7 @@ bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
|
||||
//
|
||||
|
||||
|
||||
uint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024; // 1MB
|
||||
uint32_t MinidumpMemoryRegion::max_bytes_ = 2 * 1024 * 1024; // 2MB
|
||||
|
||||
|
||||
MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
|
||||
@ -1930,9 +1930,8 @@ string MinidumpModule::debug_file() const {
|
||||
file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
|
||||
} else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
|
||||
// It's actually an MDCVInfoELF structure.
|
||||
const MDCVInfoELF* cv_record_elf =
|
||||
reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
|
||||
assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
|
||||
assert(reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])->
|
||||
cv_signature == MD_CVINFOELF_SIGNATURE);
|
||||
|
||||
// For MDCVInfoELF, the debug file is the code file.
|
||||
file = *name_;
|
||||
@ -2673,7 +2672,8 @@ const MinidumpModule* MinidumpModuleList::GetModuleForAddress(
|
||||
}
|
||||
|
||||
unsigned int module_index;
|
||||
if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
|
||||
if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
BPLOG(INFO) << "MinidumpModuleList has no module at " <<
|
||||
HexString(address);
|
||||
return NULL;
|
||||
@ -2709,7 +2709,9 @@ const MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
|
||||
}
|
||||
|
||||
unsigned int module_index;
|
||||
if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
|
||||
if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index,
|
||||
NULL /* base */, NULL /* delta */,
|
||||
NULL /* size */)) {
|
||||
BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
|
||||
return NULL;
|
||||
}
|
||||
@ -2924,7 +2926,8 @@ MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
|
||||
}
|
||||
|
||||
unsigned int region_index;
|
||||
if (!range_map_->RetrieveRange(address, ®ion_index, NULL, NULL)) {
|
||||
if (!range_map_->RetrieveRange(address, ®ion_index, NULL /* base */,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
|
||||
HexString(address);
|
||||
return NULL;
|
||||
@ -4028,7 +4031,8 @@ const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
|
||||
}
|
||||
|
||||
unsigned int info_index;
|
||||
if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
|
||||
if (!range_map_->RetrieveRange(address, &info_index, NULL /* base */,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
|
||||
HexString(address);
|
||||
return NULL;
|
||||
@ -4568,6 +4572,14 @@ static const char* get_stream_name(uint32_t stream_type) {
|
||||
return "MD_THREAD_INFO_LIST_STREAM";
|
||||
case MD_HANDLE_OPERATION_LIST_STREAM:
|
||||
return "MD_HANDLE_OPERATION_LIST_STREAM";
|
||||
case MD_TOKEN_STREAM:
|
||||
return "MD_TOKEN_STREAM";
|
||||
case MD_JAVASCRIPT_DATA_STREAM:
|
||||
return "MD_JAVASCRIPT_DATA_STREAM";
|
||||
case MD_SYSTEM_MEMORY_INFO_STREAM:
|
||||
return "MD_SYSTEM_MEMORY_INFO_STREAM";
|
||||
case MD_PROCESS_VM_COUNTERS_STREAM:
|
||||
return "MD_PROCESS_VM_COUNTERS_STREAM";
|
||||
case MD_LAST_RESERVED_STREAM:
|
||||
return "MD_LAST_RESERVED_STREAM";
|
||||
case MD_BREAKPAD_INFO_STREAM:
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "common/scoped_ptr.h"
|
||||
#include "common/stdio.h"
|
||||
#include "common/stdio_wrapper.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/processor/call_stack.h"
|
||||
#include "google_breakpad/processor/minidump.h"
|
||||
@ -267,6 +267,7 @@ ProcessResult MinidumpProcessor::Process(
|
||||
// one bad thread.
|
||||
BPLOG(ERROR) << "No stackwalker for " << thread_string;
|
||||
}
|
||||
stack->set_tid(thread_id);
|
||||
process_state->threads_.push_back(stack.release());
|
||||
process_state->thread_memory_regions_.push_back(thread_memory);
|
||||
}
|
||||
@ -745,6 +746,19 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
break;
|
||||
}
|
||||
} else if (raw_system_info->processor_architecture ==
|
||||
MD_CPU_ARCHITECTURE_X86 ||
|
||||
raw_system_info->processor_architecture ==
|
||||
MD_CPU_ARCHITECTURE_AMD64) {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
|
||||
reason.append("EXC_I386_GPFLT");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
@ -795,25 +809,26 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MD_CPU_ARCHITECTURE_AMD64:
|
||||
case MD_CPU_ARCHITECTURE_X86: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION:
|
||||
reason.append("EXC_I386_INVOP");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT:
|
||||
reason.append("EXC_INVTSSFLT");
|
||||
reason.append("EXC_I386_INVTSSFLT");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT:
|
||||
reason.append("EXC_SEGNPFLT");
|
||||
reason.append("EXC_I386_SEGNPFLT");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT:
|
||||
reason.append("EXC_STKFLT");
|
||||
reason.append("EXC_I386_STKFLT");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
|
||||
reason.append("EXC_GPFLT");
|
||||
reason.append("EXC_I386_GPFLT");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT:
|
||||
reason.append("EXC_ALIGNFLT");
|
||||
reason.append("EXC_I386_ALIGNFLT");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
@ -866,6 +881,7 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MD_CPU_ARCHITECTURE_AMD64:
|
||||
case MD_CPU_ARCHITECTURE_X86: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_X86_DIV:
|
||||
@ -966,6 +982,7 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MD_CPU_ARCHITECTURE_AMD64:
|
||||
case MD_CPU_ARCHITECTURE_X86: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_X86_SGL:
|
||||
|
@ -414,6 +414,7 @@ TEST_F(MinidumpProcessorTest, TestBasicProcessing) {
|
||||
ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE");
|
||||
ASSERT_EQ(state.crash_address(), 0x45U);
|
||||
ASSERT_EQ(state.threads()->size(), size_t(1));
|
||||
EXPECT_EQ((*state.threads())[0]->tid(), 3060U);
|
||||
ASSERT_EQ(state.requesting_thread(), 0);
|
||||
EXPECT_EQ(1171480435U, state.time_date_stamp());
|
||||
EXPECT_EQ(1171480435U, state.process_create_time());
|
||||
|
@ -625,6 +625,80 @@ TEST(Dump, CVELFShort) {
|
||||
ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier());
|
||||
}
|
||||
|
||||
// Test that a build_id that's very long is handled properly.
|
||||
TEST(Dump, CVELFLong) {
|
||||
Dump dump(0, kLittleEndian);
|
||||
String module_name(dump, "elf module");
|
||||
Section cv_info(dump);
|
||||
cv_info
|
||||
.D32(MD_CVINFOELF_SIGNATURE) // signature
|
||||
// build_id, lots of bytes
|
||||
.Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf"
|
||||
"\x37\x38\xce\xa3\x4a\x87\x01\x02\x03\x04\x05\x06\x07\x08"
|
||||
"\x09\x0a\x0b\x0c\x0d\x0e\x0f");
|
||||
|
||||
|
||||
const MDRawSystemInfo linux_x86 = {
|
||||
MD_CPU_ARCHITECTURE_X86, // processor_architecture
|
||||
6, // processor_level
|
||||
0xd08, // processor_revision
|
||||
1, // number_of_processors
|
||||
0, // product_type
|
||||
0, // major_version
|
||||
0, // minor_version
|
||||
0, // build_number
|
||||
MD_OS_LINUX, // platform_id
|
||||
0xdeadbeef, // csd_version_rva
|
||||
0x100, // suite_mask
|
||||
0, // reserved2
|
||||
{ // cpu
|
||||
{ // x86_cpu_info
|
||||
{ 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
|
||||
0x6d8, // version_information
|
||||
0xafe9fbff, // feature_information
|
||||
0xffffffff // amd_extended_cpu_features
|
||||
}
|
||||
}
|
||||
};
|
||||
String csd_version(dump, "Literally Linux");
|
||||
SystemInfo system_info(dump, linux_x86, csd_version);
|
||||
|
||||
Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
|
||||
module_name,
|
||||
0xb1054d2a,
|
||||
0x34571371,
|
||||
fixed_file_info, // from synth_minidump_unittest_data.h
|
||||
&cv_info, nullptr);
|
||||
|
||||
dump.Add(&module);
|
||||
dump.Add(&module_name);
|
||||
dump.Add(&cv_info);
|
||||
dump.Add(&system_info);
|
||||
dump.Add(&csd_version);
|
||||
dump.Finish();
|
||||
|
||||
string contents;
|
||||
ASSERT_TRUE(dump.GetContents(&contents));
|
||||
istringstream minidump_stream(contents);
|
||||
Minidump minidump(minidump_stream);
|
||||
ASSERT_TRUE(minidump.Read());
|
||||
ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
|
||||
|
||||
MinidumpModuleList *md_module_list = minidump.GetModuleList();
|
||||
ASSERT_TRUE(md_module_list != NULL);
|
||||
ASSERT_EQ(1U, md_module_list->module_count());
|
||||
|
||||
const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
|
||||
ASSERT_TRUE(md_module != NULL);
|
||||
// just the build_id, directly
|
||||
ASSERT_EQ(
|
||||
"5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f",
|
||||
md_module->code_identifier());
|
||||
// build_id truncated to GUID length and treated as such, with zero
|
||||
// age appended.
|
||||
ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier());
|
||||
}
|
||||
|
||||
TEST(Dump, OneSystemInfo) {
|
||||
Dump dump(0, kLittleEndian);
|
||||
String csd_version(dump, "Petulant Pierogi");
|
||||
|
@ -77,7 +77,7 @@
|
||||
'pathname_stripper.h',
|
||||
'postfix_evaluator-inl.h',
|
||||
'postfix_evaluator.h',
|
||||
'proc_maps_linux.cc',
|
||||
'proc_maps_linux.cc',
|
||||
'process_state.cc',
|
||||
'range_map-inl.h',
|
||||
'range_map.h',
|
||||
@ -154,6 +154,7 @@
|
||||
'minidump_unittest.cc',
|
||||
'pathname_stripper_unittest.cc',
|
||||
'postfix_evaluator_unittest.cc',
|
||||
'range_map_shrink_down_unittest.cc',
|
||||
'range_map_unittest.cc',
|
||||
'stackwalker_address_list_unittest.cc',
|
||||
'stackwalker_amd64_unittest.cc',
|
||||
|
@ -40,16 +40,29 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "processor/range_map.h"
|
||||
#include "processor/linked_ptr.h"
|
||||
#include "processor/logging.h"
|
||||
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
template<typename AddressType, typename EntryType>
|
||||
void RangeMap<AddressType, EntryType>::SetEnableShrinkDown(
|
||||
bool enable_shrink_down) {
|
||||
enable_shrink_down_ = enable_shrink_down;
|
||||
}
|
||||
|
||||
template<typename AddressType, typename EntryType>
|
||||
bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
|
||||
const AddressType &size,
|
||||
const EntryType &entry) {
|
||||
return StoreRangeInternal(base, 0 /* delta */, size, entry);
|
||||
}
|
||||
|
||||
template<typename AddressType, typename EntryType>
|
||||
bool RangeMap<AddressType, EntryType>::StoreRangeInternal(
|
||||
const AddressType &base, const AddressType &delta,
|
||||
const AddressType &size, const EntryType &entry) {
|
||||
AddressType high = base + (size - 1);
|
||||
|
||||
// Check for undersize or overflow.
|
||||
@ -57,9 +70,10 @@ bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
|
||||
// The processor will hit this case too frequently with common symbol
|
||||
// files in the size == 0 case, which is more suited to a DEBUG channel.
|
||||
// Filter those out since there's no DEBUG channel at the moment.
|
||||
BPLOG_IF(INFO, size != 0) << "StoreRange failed, " << HexString(base) <<
|
||||
"+" << HexString(size) << ", " <<
|
||||
HexString(high);
|
||||
BPLOG_IF(INFO, size != 0) << "StoreRangeInternal failed, "
|
||||
<< HexString(base) << "+" << HexString(size)
|
||||
<< ", " << HexString(high)
|
||||
<< ", delta: " << HexString(delta);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -71,53 +85,80 @@ bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
|
||||
if (iterator_base != iterator_high) {
|
||||
// Some other range begins in the space used by this range. It may be
|
||||
// contained within the space used by this range, or it may extend lower.
|
||||
// Regardless, it is an error.
|
||||
// The processor hits this case too frequently with common symbol files.
|
||||
// This is most appropriate for a DEBUG channel, but since none exists now
|
||||
// simply comment out this logging.
|
||||
//
|
||||
// AddressType other_base = iterator_base->second.base();
|
||||
// AddressType other_size = iterator_base->first - other_base + 1;
|
||||
// BPLOG(INFO) << "StoreRange failed, an existing range is contained by or "
|
||||
// "extends lower than the new range: new " <<
|
||||
// HexString(base) << "+" << HexString(size) <<
|
||||
// ", existing " << HexString(other_base) << "+" <<
|
||||
// HexString(other_size);
|
||||
|
||||
return false;
|
||||
// If enable_shrink_down_ is true, shrink the current range down, otherwise
|
||||
// this is an error.
|
||||
if (enable_shrink_down_) {
|
||||
AddressType additional_delta = iterator_base->first - base + 1;
|
||||
return StoreRangeInternal(base + additional_delta,
|
||||
delta + additional_delta,
|
||||
size - additional_delta, entry);
|
||||
} else {
|
||||
// The processor hits this case too frequently with common symbol files.
|
||||
// This is most appropriate for a DEBUG channel, but since none exists
|
||||
// now simply comment out this logging.
|
||||
// AddressType other_base = iterator_base->second.base();
|
||||
// AddressType other_size = iterator_base->first - other_base + 1;
|
||||
// BPLOG(INFO) << "StoreRangeInternal failed, an existing range is "
|
||||
// << "overlapping with the new range: new "
|
||||
// << HexString(base) << "+" << HexString(size)
|
||||
// << ", existing " << HexString(other_base) << "+"
|
||||
// << HexString(other_size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (iterator_high != map_.end()) {
|
||||
if (iterator_high->second.base() <= high) {
|
||||
// The range above this one overlaps with this one. It may fully
|
||||
// contain this range, or it may begin within this range and extend
|
||||
// higher. Regardless, it's an error.
|
||||
// The processor hits this case too frequently with common symbol files.
|
||||
// This is most appropriate for a DEBUG channel, but since none exists now
|
||||
// simply comment out this logging.
|
||||
//
|
||||
// AddressType other_base = iterator_high->second.base();
|
||||
// AddressType other_size = iterator_high->first - other_base + 1;
|
||||
// BPLOG(INFO) << "StoreRange failed, an existing range contains or "
|
||||
// "extends higher than the new range: new " <<
|
||||
// HexString(base) << "+" << HexString(size) <<
|
||||
// ", existing " << HexString(other_base) << "+" <<
|
||||
// HexString(other_size);
|
||||
return false;
|
||||
// higher. If enable_shrink_down_ is true, shrink the other range down,
|
||||
// otherwise this is an error.
|
||||
if (enable_shrink_down_ && iterator_high->first > high) {
|
||||
// Shrink the other range down.
|
||||
AddressType other_high = iterator_high->first;
|
||||
AddressType additional_delta =
|
||||
high - iterator_high->second.base() + 1;
|
||||
EntryType other_entry;
|
||||
AddressType other_base = AddressType();
|
||||
AddressType other_size = AddressType();
|
||||
AddressType other_delta = AddressType();
|
||||
RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
|
||||
&other_size);
|
||||
map_.erase(iterator_high);
|
||||
map_.insert(MapValue(other_high,
|
||||
Range(other_base + additional_delta,
|
||||
other_delta + additional_delta,
|
||||
other_entry)));
|
||||
// Retry to store this range.
|
||||
return StoreRangeInternal(base, delta, size, entry);
|
||||
} else {
|
||||
// The processor hits this case too frequently with common symbol files.
|
||||
// This is most appropriate for a DEBUG channel, but since none exists
|
||||
// now simply comment out this logging.
|
||||
//
|
||||
// AddressType other_base = iterator_high->second.base();
|
||||
// AddressType other_size = iterator_high->first - other_base + 1;
|
||||
// BPLOG(INFO) << "StoreRangeInternal failed, an existing range "
|
||||
// << "contains or extends higher than the new range: new "
|
||||
// << HexString(base) << "+" << HexString(size)
|
||||
// << ", existing " << HexString(other_base) << "+"
|
||||
// << HexString(other_size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the range in the map by its high address, so that lower_bound can
|
||||
// be used to quickly locate a range by address.
|
||||
map_.insert(MapValue(high, Range(base, entry)));
|
||||
map_.insert(MapValue(high, Range(base, delta, entry)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType, typename EntryType>
|
||||
bool RangeMap<AddressType, EntryType>::RetrieveRange(
|
||||
const AddressType &address, EntryType *entry,
|
||||
AddressType *entry_base, AddressType *entry_size) const {
|
||||
const AddressType &address, EntryType *entry, AddressType *entry_base,
|
||||
AddressType *entry_delta, AddressType *entry_size) const {
|
||||
BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|";
|
||||
assert(entry);
|
||||
|
||||
@ -136,6 +177,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveRange(
|
||||
*entry = iterator->second.entry();
|
||||
if (entry_base)
|
||||
*entry_base = iterator->second.base();
|
||||
if (entry_delta)
|
||||
*entry_delta = iterator->second.delta();
|
||||
if (entry_size)
|
||||
*entry_size = iterator->first - iterator->second.base() + 1;
|
||||
|
||||
@ -145,13 +188,13 @@ bool RangeMap<AddressType, EntryType>::RetrieveRange(
|
||||
|
||||
template<typename AddressType, typename EntryType>
|
||||
bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
|
||||
const AddressType &address, EntryType *entry,
|
||||
AddressType *entry_base, AddressType *entry_size) const {
|
||||
const AddressType &address, EntryType *entry, AddressType *entry_base,
|
||||
AddressType *entry_delta, AddressType *entry_size) const {
|
||||
BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|";
|
||||
assert(entry);
|
||||
|
||||
// If address is within a range, RetrieveRange can handle it.
|
||||
if (RetrieveRange(address, entry, entry_base, entry_size))
|
||||
if (RetrieveRange(address, entry, entry_base, entry_delta, entry_size))
|
||||
return true;
|
||||
|
||||
// upper_bound gives the first element whose key is greater than address,
|
||||
@ -167,6 +210,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
|
||||
*entry = iterator->second.entry();
|
||||
if (entry_base)
|
||||
*entry_base = iterator->second.base();
|
||||
if (entry_delta)
|
||||
*entry_delta = iterator->second.delta();
|
||||
if (entry_size)
|
||||
*entry_size = iterator->first - iterator->second.base() + 1;
|
||||
|
||||
@ -176,8 +221,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
|
||||
|
||||
template<typename AddressType, typename EntryType>
|
||||
bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
|
||||
int index, EntryType *entry,
|
||||
AddressType *entry_base, AddressType *entry_size) const {
|
||||
int index, EntryType *entry, AddressType *entry_base,
|
||||
AddressType *entry_delta, AddressType *entry_size) const {
|
||||
BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|";
|
||||
assert(entry);
|
||||
|
||||
@ -195,6 +240,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
|
||||
*entry = iterator->second.entry();
|
||||
if (entry_base)
|
||||
*entry_base = iterator->second.base();
|
||||
if (entry_delta)
|
||||
*entry_delta = iterator->second.delta();
|
||||
if (entry_size)
|
||||
*entry_size = iterator->first - iterator->second.base() + 1;
|
||||
|
||||
|
@ -52,40 +52,55 @@ template<class, class> class RangeMapSerializer;
|
||||
template<typename AddressType, typename EntryType>
|
||||
class RangeMap {
|
||||
public:
|
||||
RangeMap() : map_() {}
|
||||
RangeMap() : enable_shrink_down_(false), map_() {}
|
||||
|
||||
// |enable_shrink_down| tells whether overlapping ranges can be shrunk down.
|
||||
// If true, then adding a new range that overlaps with an existing one can
|
||||
// be a successful operation. The range which ends at the higher address
|
||||
// will be shrunk down by moving its start position to a higher address so
|
||||
// that it does not overlap anymore.
|
||||
void SetEnableShrinkDown(bool enable_shrink_down);
|
||||
|
||||
// Inserts a range into the map. Returns false for a parameter error,
|
||||
// or if the location of the range would conflict with a range already
|
||||
// stored in the map.
|
||||
bool StoreRange(const AddressType &base,
|
||||
const AddressType &size,
|
||||
// stored in the map. If enable_shrink_down is true and there is an overlap
|
||||
// between the current range and some other range (already in the map),
|
||||
// shrink down the range which ends at a higher address.
|
||||
bool StoreRange(const AddressType &base, const AddressType &size,
|
||||
const EntryType &entry);
|
||||
|
||||
// Locates the range encompassing the supplied address. If there is
|
||||
// no such range, returns false. entry_base and entry_size, if non-NULL,
|
||||
// are set to the base and size of the entry's range.
|
||||
// Locates the range encompassing the supplied address. If there is no such
|
||||
// range, returns false. entry_base, entry_delta, and entry_size, if
|
||||
// non-NULL, are set to the base, delta, and size of the entry's range.
|
||||
// A positive entry delta (> 0) indicates that there was an overlap and the
|
||||
// entry was shrunk down (original start address was increased by delta).
|
||||
bool RetrieveRange(const AddressType &address, EntryType *entry,
|
||||
AddressType *entry_base, AddressType *entry_size) const;
|
||||
AddressType *entry_base, AddressType *entry_delta,
|
||||
AddressType *entry_size) const;
|
||||
|
||||
// Locates the range encompassing the supplied address, if one exists.
|
||||
// If no range encompasses the supplied address, locates the nearest range
|
||||
// to the supplied address that is lower than the address. Returns false
|
||||
// if no range meets these criteria. entry_base and entry_size, if
|
||||
// non-NULL, are set to the base and size of the entry's range.
|
||||
// if no range meets these criteria. entry_base, entry_delta, and entry_size,
|
||||
// if non-NULL, are set to the base, delta, and size of the entry's range.
|
||||
// A positive entry delta (> 0) indicates that there was an overlap and the
|
||||
// entry was shrunk down (original start address was increased by delta).
|
||||
bool RetrieveNearestRange(const AddressType &address, EntryType *entry,
|
||||
AddressType *entry_base, AddressType *entry_size)
|
||||
const;
|
||||
AddressType *entry_base, AddressType *entry_delta,
|
||||
AddressType *entry_size) const;
|
||||
|
||||
// Treating all ranges as a list ordered by the address spaces that they
|
||||
// occupy, locates the range at the index specified by index. Returns
|
||||
// false if index is larger than the number of ranges stored. entry_base
|
||||
// and entry_size, if non-NULL, are set to the base and size of the entry's
|
||||
// range.
|
||||
// false if index is larger than the number of ranges stored. entry_base,
|
||||
// entry_delta, and entry_size, if non-NULL, are set to the base, delta, and
|
||||
// size of the entry's range.
|
||||
// A positive entry delta (> 0) indicates that there was an overlap and the
|
||||
// entry was shrunk down (original start address was increased by delta).
|
||||
//
|
||||
// RetrieveRangeAtIndex is not optimized for speedy operation.
|
||||
bool RetrieveRangeAtIndex(int index, EntryType *entry,
|
||||
AddressType *entry_base, AddressType *entry_size)
|
||||
const;
|
||||
AddressType *entry_base, AddressType *entry_delta,
|
||||
AddressType *entry_size) const;
|
||||
|
||||
// Returns the number of ranges stored in the RangeMap.
|
||||
int GetCount() const;
|
||||
@ -99,12 +114,19 @@ class RangeMap {
|
||||
friend class ModuleComparer;
|
||||
friend class RangeMapSerializer<AddressType, EntryType>;
|
||||
|
||||
// Same a StoreRange() with the only exception that the |delta| can be
|
||||
// passed in.
|
||||
bool StoreRangeInternal(const AddressType &base, const AddressType &delta,
|
||||
const AddressType &size, const EntryType &entry);
|
||||
|
||||
class Range {
|
||||
public:
|
||||
Range(const AddressType &base, const EntryType &entry)
|
||||
: base_(base), entry_(entry) {}
|
||||
Range(const AddressType &base, const AddressType &delta,
|
||||
const EntryType &entry)
|
||||
: base_(base), delta_(delta), entry_(entry) {}
|
||||
|
||||
AddressType base() const { return base_; }
|
||||
AddressType delta() const { return delta_; }
|
||||
EntryType entry() const { return entry_; }
|
||||
|
||||
private:
|
||||
@ -112,6 +134,9 @@ class RangeMap {
|
||||
// be stored, because RangeMap uses it as the key to the map.
|
||||
const AddressType base_;
|
||||
|
||||
// The delta when the range is shrunk down.
|
||||
const AddressType delta_;
|
||||
|
||||
// The entry corresponding to a range.
|
||||
const EntryType entry_;
|
||||
};
|
||||
@ -121,6 +146,9 @@ class RangeMap {
|
||||
typedef typename AddressToRangeMap::const_iterator MapConstIterator;
|
||||
typedef typename AddressToRangeMap::value_type MapValue;
|
||||
|
||||
// Whether overlapping ranges can be shrunk down.
|
||||
bool enable_shrink_down_;
|
||||
|
||||
// Maps the high address of each range to a EntryType.
|
||||
AddressToRangeMap map_;
|
||||
};
|
||||
|
355
src/processor/range_map_shrink_down_unittest.cc
Normal file
355
src/processor/range_map_shrink_down_unittest.cc
Normal file
@ -0,0 +1,355 @@
|
||||
// Copyright (c) 2016, 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
|
||||
|
||||
// range_map_shrink_down_unittest.cc: Unit tests for RangeMap that specifically
|
||||
// test shrink down when ranges overlap.
|
||||
//
|
||||
// Author: Ivan Penkov
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "processor/range_map-inl.h"
|
||||
|
||||
#include "breakpad_googletest_includes.h"
|
||||
#include "common/scoped_ptr.h"
|
||||
#include "processor/linked_ptr.h"
|
||||
#include "processor/logging.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using google_breakpad::linked_ptr;
|
||||
using google_breakpad::scoped_ptr;
|
||||
using google_breakpad::RangeMap;
|
||||
|
||||
// A CountedObject holds an int. A global (not thread safe!) count of
|
||||
// allocated CountedObjects is maintained to help test memory management.
|
||||
class CountedObject {
|
||||
public:
|
||||
explicit CountedObject(int id) : id_(id) { ++count_; }
|
||||
~CountedObject() { --count_; }
|
||||
|
||||
static int count() { return count_; }
|
||||
int id() const { return id_; }
|
||||
|
||||
private:
|
||||
static int count_;
|
||||
int id_;
|
||||
};
|
||||
|
||||
int CountedObject::count_;
|
||||
|
||||
typedef int AddressType;
|
||||
typedef RangeMap<AddressType, linked_ptr<CountedObject>> TestMap;
|
||||
|
||||
// Same range cannot be stored wice.
|
||||
TEST(RangeMap, TestShinkDown_SameRange) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
|
||||
object_1));
|
||||
|
||||
// Same range cannot be stored wice.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_FALSE(range_map.StoreRange(0 /* base address */, 100 /* size */,
|
||||
object_2));
|
||||
}
|
||||
|
||||
// If a range is completely contained by another range, then the larger range
|
||||
// should be shrinked down.
|
||||
TEST(RangeMap, TestShinkDown_CompletelyContained) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
// Larger range is added first.
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
|
||||
object_1));
|
||||
// Smaller (contained) range is added second.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */,
|
||||
object_2));
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The first range contains the second, so the first range should have been
|
||||
// shrunk to [90, 99]. Range [0, 9] should be free.
|
||||
EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(90, retrieved_base);
|
||||
EXPECT_EQ(90, retrieved_delta);
|
||||
EXPECT_EQ(10, retrieved_size);
|
||||
// Validate the properties of the smaller range (should be untouched).
|
||||
EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(10, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(80, retrieved_size);
|
||||
}
|
||||
|
||||
// Same as the previous test, however the larger range is added second.
|
||||
TEST(RangeMap, TestShinkDown_CompletelyContained_LargerAddedSecond) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
// Smaller (contained) range is added first.
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */,
|
||||
object_1));
|
||||
// Larger range is added second.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
|
||||
object_2));
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The second range contains the first, so the second range should have been
|
||||
// shrunk to [90, 99]. Range [0, 9] should be free.
|
||||
EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(90, retrieved_base);
|
||||
EXPECT_EQ(90, retrieved_delta);
|
||||
EXPECT_EQ(10, retrieved_size);
|
||||
// Validate the properties of the smaller range (should be untouched).
|
||||
EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(10, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(80, retrieved_size);
|
||||
}
|
||||
|
||||
TEST(RangeMap, TestShinkDown_PartialOverlap_AtBeginning) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
|
||||
object_1));
|
||||
|
||||
// Partial overlap at the beginning of the new range.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(90 /* base address */, 110 /* size */,
|
||||
object_2));
|
||||
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The second range is supposed to be shrunk down so the following address
|
||||
// should resize in the first range.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(0, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(100, retrieved_size);
|
||||
// Validate the properties of the shrunk down range.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(100, retrieved_base);
|
||||
EXPECT_EQ(10, retrieved_delta);
|
||||
EXPECT_EQ(100, retrieved_size);
|
||||
}
|
||||
|
||||
TEST(RangeMap, TestShinkDown_PartialOverlap_AtEnd) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 50 /* size */,
|
||||
object_1));
|
||||
|
||||
// Partial overlap at the end of the new range.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 70 /* size */,
|
||||
object_2));
|
||||
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The first range is supposed to be shrunk down so the following address
|
||||
// should resize in the first range.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(69, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(0, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(70, retrieved_size);
|
||||
// Validate the properties of the shrunk down range.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(70, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(70, retrieved_base);
|
||||
EXPECT_EQ(20, retrieved_delta);
|
||||
EXPECT_EQ(30, retrieved_size);
|
||||
}
|
||||
|
||||
// A new range is overlapped at both ends. The new range and the range
|
||||
// that overlaps at the end should be shrink. The range that overlaps at the
|
||||
// beginning should be left untouched.
|
||||
TEST(RangeMap, TestShinkDown_OverlapAtBothEnds) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
// This should overlap object_3 at the beginning.
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
|
||||
object_1));
|
||||
|
||||
// This should overlap object_3 at the end.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */,
|
||||
object_2));
|
||||
|
||||
// This should be overlapped on both ends by object_1 and object_2.
|
||||
linked_ptr<CountedObject> object_3(new CountedObject(3));
|
||||
EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 100 /* size */,
|
||||
object_3));
|
||||
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The first range should be intact.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(0, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(0, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(100, retrieved_size);
|
||||
// The second range should be shrunk down by 50.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(150, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(150, retrieved_base);
|
||||
EXPECT_EQ(50, retrieved_delta);
|
||||
EXPECT_EQ(50, retrieved_size);
|
||||
// The third range (in the middle) should be shrunk down by 50.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(3, object->id());
|
||||
EXPECT_EQ(100, retrieved_base);
|
||||
EXPECT_EQ(50, retrieved_delta);
|
||||
EXPECT_EQ(50, retrieved_size);
|
||||
}
|
||||
|
||||
TEST(RangeMap, TestShinkDown_MultipleConflicts) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
// This should overlap with object_3.
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */,
|
||||
object_1));
|
||||
|
||||
// This should also overlap with object_3 but after object_1.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */,
|
||||
object_2));
|
||||
|
||||
// This should be overlapped on both object_1 and object_2. Since
|
||||
// object_3 ends with the higher address it must be shrunk.
|
||||
linked_ptr<CountedObject> object_3(new CountedObject(3));
|
||||
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 300 /* size */,
|
||||
object_3));
|
||||
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The first range should be intact.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(10, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(90, retrieved_size);
|
||||
// The second range should be intact.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(100, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(100, retrieved_size);
|
||||
// The third range should be shrunk down by 200.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(299, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(3, object->id());
|
||||
EXPECT_EQ(200, retrieved_base);
|
||||
EXPECT_EQ(200, retrieved_delta);
|
||||
EXPECT_EQ(100, retrieved_size);
|
||||
}
|
||||
|
||||
// Adding two ranges without overlap should succeed and the ranges should
|
||||
// be left intact.
|
||||
TEST(RangeMap, TestShinkDown_NoConflicts) {
|
||||
TestMap range_map;
|
||||
range_map.SetEnableShrinkDown(true);
|
||||
// Adding range 1.
|
||||
linked_ptr<CountedObject> object_1(new CountedObject(1));
|
||||
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */,
|
||||
object_1));
|
||||
|
||||
// Adding range 2 - no overlap with range 1.
|
||||
linked_ptr<CountedObject> object_2(new CountedObject(2));
|
||||
EXPECT_TRUE(range_map.StoreRange(110 /* base address */, 90 /* size */,
|
||||
object_2));
|
||||
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
// The first range should be intact.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(1, object->id());
|
||||
EXPECT_EQ(10, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(90, retrieved_size);
|
||||
// The second range should be intact.
|
||||
EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
|
||||
&retrieved_delta, &retrieved_size));
|
||||
EXPECT_EQ(2, object->id());
|
||||
EXPECT_EQ(110, retrieved_base);
|
||||
EXPECT_EQ(0, retrieved_delta);
|
||||
EXPECT_EQ(90, retrieved_size);
|
||||
}
|
||||
|
||||
} // namespace
|
@ -166,8 +166,10 @@ static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) {
|
||||
linked_ptr<CountedObject> object;
|
||||
AddressType retrieved_base = AddressType();
|
||||
AddressType retrieved_size = AddressType();
|
||||
AddressType retrieved_delta = AddressType();
|
||||
bool retrieved = range_map->RetrieveRange(address, &object,
|
||||
&retrieved_base,
|
||||
&retrieved_delta,
|
||||
&retrieved_size);
|
||||
|
||||
bool observed_result = retrieved && object->id() == range_test->id;
|
||||
@ -209,10 +211,12 @@ static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) {
|
||||
|
||||
linked_ptr<CountedObject> nearest_object;
|
||||
AddressType nearest_base = AddressType();
|
||||
AddressType nearest_delta = AddressType();
|
||||
AddressType nearest_size = AddressType();
|
||||
bool retrieved_nearest = range_map->RetrieveNearestRange(address,
|
||||
&nearest_object,
|
||||
&nearest_base,
|
||||
&nearest_delta,
|
||||
&nearest_size);
|
||||
|
||||
// When checking one greater than the high side, RetrieveNearestRange
|
||||
@ -274,7 +278,8 @@ static bool RetrieveIndexTest(TestMap *range_map, int set) {
|
||||
int object_count = range_map->GetCount();
|
||||
for (int object_index = 0; object_index < object_count; ++object_index) {
|
||||
AddressType base;
|
||||
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, NULL)) {
|
||||
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, "
|
||||
"expected success, observed failure\n",
|
||||
set, object_index);
|
||||
@ -314,7 +319,8 @@ static bool RetrieveIndexTest(TestMap *range_map, int set) {
|
||||
|
||||
// Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that
|
||||
// are too high.
|
||||
if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL, NULL)) {
|
||||
if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL /* base */,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d (too large), "
|
||||
"expected failure, observed success\n",
|
||||
set, object_count);
|
||||
@ -343,7 +349,8 @@ static bool RetriveAtIndexTest2() {
|
||||
int object_count = range_map->GetCount();
|
||||
for (int object_index = 0; object_index < object_count; ++object_index) {
|
||||
AddressType base;
|
||||
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, NULL)) {
|
||||
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base,
|
||||
NULL /* delta */, NULL /* size */)) {
|
||||
fprintf(stderr, "FAILED: RetrieveAtIndexTest2 index %d, "
|
||||
"expected success, observed failure\n", object_index);
|
||||
return false;
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/stdio.h"
|
||||
#include "common/stdio_wrapper.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/processor/call_stack.h"
|
||||
#include "google_breakpad/processor/code_module.h"
|
||||
|
@ -164,6 +164,12 @@ bool StackwalkerAMD64::IsEndOfStack(uint64_t caller_rip, uint64_t caller_rsp,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if `ptr` is not in x86-64 canonical form.
|
||||
// https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
|
||||
static bool is_non_canonical(uint64_t ptr) {
|
||||
return ptr > 0x7FFFFFFFFFFF && ptr < 0xFFFF800000000000;
|
||||
}
|
||||
|
||||
StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
|
||||
const vector<StackFrame*>& frames) {
|
||||
StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
|
||||
@ -186,11 +192,22 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
|
||||
// %caller_rip = *(%callee_rbp + 8)
|
||||
// %caller_rbp = *(%callee_rbp)
|
||||
|
||||
// If rbp is not 8-byte aligned it can't be a frame pointer.
|
||||
if (last_rbp % 8 != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t caller_rip, caller_rbp;
|
||||
if (memory_->GetMemoryAtAddress(last_rbp + 8, &caller_rip) &&
|
||||
memory_->GetMemoryAtAddress(last_rbp, &caller_rbp)) {
|
||||
uint64_t caller_rsp = last_rbp + 16;
|
||||
|
||||
// If the recovered rip is not a canonical address it can't be
|
||||
// the return address, so rbp must not have been a frame pointer.
|
||||
if (is_non_canonical(caller_rip)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Simple sanity check that the stack is growing downwards as expected.
|
||||
if (IsEndOfStack(caller_rip, caller_rsp, last_rsp) ||
|
||||
caller_rbp < last_rbp) {
|
||||
|
@ -72,8 +72,8 @@ class StackwalkerAMD64Fixture {
|
||||
: stack_section(kLittleEndian),
|
||||
// Give the two modules reasonable standard locations and names
|
||||
// for tests to play with.
|
||||
module1(0x40000000c0000000ULL, 0x10000, "module1", "version1"),
|
||||
module2(0x50000000b0000000ULL, 0x10000, "module2", "version2") {
|
||||
module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"),
|
||||
module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") {
|
||||
// Identify the system as a Linux system.
|
||||
system_info.os = "Linux";
|
||||
system_info.os_short = "linux";
|
||||
@ -149,7 +149,7 @@ TEST_F(SanityCheck, NoResolver) {
|
||||
// provide any call frame information, so trying to reconstruct the
|
||||
// context frame's caller should fail. So there's no need for us to
|
||||
// provide stack contents.
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = 0x8000000080000000ULL;
|
||||
|
||||
StackFrameSymbolizer frame_symbolizer(NULL, NULL);
|
||||
@ -176,7 +176,7 @@ TEST_F(GetContextFrame, Simple) {
|
||||
// provide any call frame information, so trying to reconstruct the
|
||||
// context frame's caller should fail. So there's no need for us to
|
||||
// provide stack contents.
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = 0x8000000080000000ULL;
|
||||
|
||||
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
|
||||
@ -200,7 +200,7 @@ TEST_F(GetContextFrame, Simple) {
|
||||
// The stackwalker should be able to produce the context frame even
|
||||
// without stack memory present.
|
||||
TEST_F(GetContextFrame, NoStackMemory) {
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = 0x8000000080000000ULL;
|
||||
|
||||
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
|
||||
@ -230,23 +230,23 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
|
||||
// Force scanning through three frames to ensure that the
|
||||
// stack pointer is set properly in scan-recovered frames.
|
||||
stack_section.start() = 0x8000000080000000ULL;
|
||||
uint64_t return_address1 = 0x50000000b0000100ULL;
|
||||
uint64_t return_address2 = 0x50000000b0000900ULL;
|
||||
uint64_t return_address1 = 0x00007500b0000100ULL;
|
||||
uint64_t return_address2 = 0x00007500b0000900ULL;
|
||||
Label frame1_sp, frame2_sp, frame1_rbp;
|
||||
stack_section
|
||||
// frame 0
|
||||
.Append(16, 0) // space
|
||||
|
||||
.D64(0x40000000b0000000ULL) // junk that's not
|
||||
.D64(0x50000000d0000000ULL) // a return address
|
||||
.D64(0x00007400b0000000ULL) // junk that's not
|
||||
.D64(0x00007500d0000000ULL) // a return address
|
||||
|
||||
.D64(return_address1) // actual return address
|
||||
// frame 1
|
||||
.Mark(&frame1_sp)
|
||||
.Append(16, 0) // space
|
||||
|
||||
.D64(0x40000000b0000000ULL) // more junk
|
||||
.D64(0x50000000d0000000ULL)
|
||||
.D64(0x00007400b0000000ULL) // more junk
|
||||
.D64(0x00007500d0000000ULL)
|
||||
|
||||
.Mark(&frame1_rbp)
|
||||
.D64(stack_section.start()) // This is in the right place to be
|
||||
@ -260,7 +260,7 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
|
||||
|
||||
RegionFromSection();
|
||||
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = frame1_rbp.Value();
|
||||
raw_context.rsp = stack_section.start().Value();
|
||||
|
||||
@ -308,18 +308,18 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
|
||||
// it is only considered a valid return address if it
|
||||
// lies within a function's bounds.
|
||||
stack_section.start() = 0x8000000080000000ULL;
|
||||
uint64_t return_address = 0x50000000b0000110ULL;
|
||||
uint64_t return_address = 0x00007500b0000110ULL;
|
||||
Label frame1_sp, frame1_rbp;
|
||||
|
||||
stack_section
|
||||
// frame 0
|
||||
.Append(16, 0) // space
|
||||
|
||||
.D64(0x40000000b0000000ULL) // junk that's not
|
||||
.D64(0x50000000b0000000ULL) // a return address
|
||||
.D64(0x00007400b0000000ULL) // junk that's not
|
||||
.D64(0x00007500b0000000ULL) // a return address
|
||||
|
||||
.D64(0x40000000c0001000ULL) // a couple of plausible addresses
|
||||
.D64(0x50000000b000aaaaULL) // that are not within functions
|
||||
.D64(0x00007400c0001000ULL) // a couple of plausible addresses
|
||||
.D64(0x00007500b000aaaaULL) // that are not within functions
|
||||
|
||||
.D64(return_address) // actual return address
|
||||
// frame 1
|
||||
@ -328,7 +328,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
|
||||
.Mark(&frame1_rbp);
|
||||
RegionFromSection();
|
||||
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = frame1_rbp.Value();
|
||||
raw_context.rsp = stack_section.start().Value();
|
||||
|
||||
@ -355,7 +355,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||
EXPECT_EQ("platypus", frame0->function_name);
|
||||
EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
|
||||
EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
|
||||
|
||||
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
|
||||
@ -367,7 +367,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
|
||||
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
|
||||
EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
|
||||
EXPECT_EQ("echidna", frame1->function_name);
|
||||
EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
|
||||
EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
|
||||
}
|
||||
|
||||
// StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an
|
||||
@ -502,6 +502,107 @@ TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) {
|
||||
}
|
||||
}
|
||||
|
||||
// Don't use frame pointer recovery if %rbp is not 8-byte aligned, which
|
||||
// indicates that it's not being used as a frame pointer.
|
||||
TEST_F(GetCallerFrame, FramePointerNotAligned) {
|
||||
stack_section.start() = 0x8000000080000000ULL;
|
||||
uint64_t return_address1 = 0x00007500b0000100ULL;
|
||||
Label frame0_rbp, not_frame1_rbp, frame1_sp;
|
||||
stack_section
|
||||
// frame 0
|
||||
.Align(8, 0)
|
||||
.Append(2, 0) // mis-align the frame pointer
|
||||
.Mark(&frame0_rbp)
|
||||
.D64(not_frame1_rbp) // not the previous frame pointer
|
||||
.D64(0x00007500b0000a00ULL) // plausible but wrong return address
|
||||
.Align(8, 0)
|
||||
.D64(return_address1) // return address
|
||||
// frame 1
|
||||
.Mark(&frame1_sp)
|
||||
.Mark(¬_frame1_rbp)
|
||||
.Append(32, 0); // end of stack
|
||||
|
||||
|
||||
RegionFromSection();
|
||||
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = frame0_rbp.Value();
|
||||
raw_context.rsp = stack_section.start().Value();
|
||||
|
||||
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
|
||||
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
|
||||
&frame_symbolizer);
|
||||
vector<const CodeModule*> modules_without_symbols;
|
||||
vector<const CodeModule*> modules_with_corrupt_symbols;
|
||||
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
|
||||
&modules_with_corrupt_symbols));
|
||||
frames = call_stack.frames();
|
||||
ASSERT_EQ(2U, frames->size());
|
||||
|
||||
StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||
EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
|
||||
|
||||
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
|
||||
ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
|
||||
StackFrameAMD64::CONTEXT_VALID_RSP),
|
||||
frame1->context_validity);
|
||||
EXPECT_EQ(return_address1, frame1->context.rip);
|
||||
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
|
||||
}
|
||||
|
||||
// Don't use frame pointer recovery if the recovered %rip is not
|
||||
// a canonical x86-64 address.
|
||||
TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) {
|
||||
stack_section.start() = 0x8000000080000000ULL;
|
||||
uint64_t return_address1 = 0x00007500b0000100ULL;
|
||||
Label frame0_rbp, frame1_sp, not_frame1_bp;
|
||||
stack_section
|
||||
// frame 0
|
||||
.Align(8, 0)
|
||||
.Mark(&frame0_rbp)
|
||||
.D64(not_frame1_bp) // some junk on the stack
|
||||
.D64(0xDADADADADADADADA) // not the return address
|
||||
.D64(return_address1) // return address
|
||||
// frame 1
|
||||
.Mark(&frame1_sp)
|
||||
.Append(16, 0)
|
||||
.Mark(¬_frame1_bp)
|
||||
.Append(32, 0); // end of stack
|
||||
|
||||
|
||||
RegionFromSection();
|
||||
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = frame0_rbp.Value();
|
||||
raw_context.rsp = stack_section.start().Value();
|
||||
|
||||
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
|
||||
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
|
||||
&frame_symbolizer);
|
||||
vector<const CodeModule*> modules_without_symbols;
|
||||
vector<const CodeModule*> modules_with_corrupt_symbols;
|
||||
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
|
||||
&modules_with_corrupt_symbols));
|
||||
frames = call_stack.frames();
|
||||
ASSERT_EQ(2U, frames->size());
|
||||
|
||||
StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||
EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
|
||||
|
||||
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
|
||||
ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
|
||||
StackFrameAMD64::CONTEXT_VALID_RSP),
|
||||
frame1->context_validity);
|
||||
EXPECT_EQ(return_address1, frame1->context.rip);
|
||||
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
|
||||
}
|
||||
|
||||
// Test that set_max_frames_scanned prevents using stack scanning
|
||||
// to find caller frames.
|
||||
TEST_F(GetCallerFrame, ScanningNotAllowed) {
|
||||
@ -509,23 +610,23 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) {
|
||||
// only addresses located within loaded modules are
|
||||
// considered valid return addresses.
|
||||
stack_section.start() = 0x8000000080000000ULL;
|
||||
uint64_t return_address1 = 0x50000000b0000100ULL;
|
||||
uint64_t return_address2 = 0x50000000b0000900ULL;
|
||||
uint64_t return_address1 = 0x00007500b0000100ULL;
|
||||
uint64_t return_address2 = 0x00007500b0000900ULL;
|
||||
Label frame1_sp, frame2_sp, frame1_rbp;
|
||||
stack_section
|
||||
// frame 0
|
||||
.Append(16, 0) // space
|
||||
|
||||
.D64(0x40000000b0000000ULL) // junk that's not
|
||||
.D64(0x50000000d0000000ULL) // a return address
|
||||
.D64(0x00007400b0000000ULL) // junk that's not
|
||||
.D64(0x00007500d0000000ULL) // a return address
|
||||
|
||||
.D64(return_address1) // actual return address
|
||||
// frame 1
|
||||
.Mark(&frame1_sp)
|
||||
.Append(16, 0) // space
|
||||
|
||||
.D64(0x40000000b0000000ULL) // more junk
|
||||
.D64(0x50000000d0000000ULL)
|
||||
.D64(0x00007400b0000000ULL) // more junk
|
||||
.D64(0x00007500d0000000ULL)
|
||||
|
||||
.Mark(&frame1_rbp)
|
||||
.D64(stack_section.start()) // This is in the right place to be
|
||||
@ -539,7 +640,7 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) {
|
||||
|
||||
RegionFromSection();
|
||||
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = frame1_rbp.Value();
|
||||
raw_context.rsp = stack_section.start().Value();
|
||||
|
||||
@ -570,18 +671,18 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
|
||||
// %rbp directly below the return address, assume that it is indeed the
|
||||
// next frame's %rbp.
|
||||
stack_section.start() = 0x8000000080000000ULL;
|
||||
uint64_t return_address = 0x50000000b0000110ULL;
|
||||
uint64_t return_address = 0x00007500b0000110ULL;
|
||||
Label frame0_rbp, frame1_sp, frame1_rbp;
|
||||
|
||||
stack_section
|
||||
// frame 0
|
||||
.Append(16, 0) // space
|
||||
|
||||
.D64(0x40000000b0000000ULL) // junk that's not
|
||||
.D64(0x50000000b0000000ULL) // a return address
|
||||
.D64(0x00007400b0000000ULL) // junk that's not
|
||||
.D64(0x00007500b0000000ULL) // a return address
|
||||
|
||||
.D64(0x40000000c0001000ULL) // a couple of plausible addresses
|
||||
.D64(0x50000000b000aaaaULL) // that are not within functions
|
||||
.D64(0x00007400c0001000ULL) // a couple of plausible addresses
|
||||
.D64(0x00007500b000aaaaULL) // that are not within functions
|
||||
|
||||
.Mark(&frame0_rbp)
|
||||
.D64(frame1_rbp) // caller-pushed %rbp
|
||||
@ -592,7 +693,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
|
||||
.Mark(&frame1_rbp); // end of stack
|
||||
RegionFromSection();
|
||||
|
||||
raw_context.rip = 0x40000000c0000200ULL;
|
||||
raw_context.rip = 0x00007400c0000200ULL;
|
||||
raw_context.rbp = frame0_rbp.Value();
|
||||
raw_context.rsp = stack_section.start().Value();
|
||||
|
||||
@ -620,7 +721,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
|
||||
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||
EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp);
|
||||
EXPECT_EQ("sasquatch", frame0->function_name);
|
||||
EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
|
||||
EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
|
||||
|
||||
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
|
||||
@ -632,7 +733,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
|
||||
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
|
||||
EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
|
||||
EXPECT_EQ("yeti", frame1->function_name);
|
||||
EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
|
||||
EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
|
||||
}
|
||||
|
||||
struct CFIFixture: public StackwalkerAMD64Fixture {
|
||||
@ -663,7 +764,7 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
|
||||
|
||||
// Provide some distinctive values for the caller's registers.
|
||||
expected.rsp = 0x8000000080000000ULL;
|
||||
expected.rip = 0x40000000c0005510ULL;
|
||||
expected.rip = 0x00007400c0005510ULL;
|
||||
expected.rbp = 0x68995b1de4700266ULL;
|
||||
expected.rbx = 0x5a5beeb38de23be8ULL;
|
||||
expected.r12 = 0xed1b02e8cc0fc79cULL;
|
||||
@ -700,7 +801,7 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||
EXPECT_EQ("enchiridion", frame0->function_name);
|
||||
EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base);
|
||||
EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base);
|
||||
|
||||
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
||||
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||
@ -733,9 +834,9 @@ class CFI: public CFIFixture, public Test { };
|
||||
TEST_F(CFI, At4000) {
|
||||
Label frame1_rsp = expected.rsp;
|
||||
stack_section
|
||||
.D64(0x40000000c0005510ULL) // return address
|
||||
.D64(0x00007400c0005510ULL) // return address
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004000ULL;
|
||||
raw_context.rip = 0x00007400c0004000ULL;
|
||||
CheckWalk();
|
||||
}
|
||||
|
||||
@ -743,9 +844,9 @@ TEST_F(CFI, At4001) {
|
||||
Label frame1_rsp = expected.rsp;
|
||||
stack_section
|
||||
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
|
||||
.D64(0x40000000c0005510ULL) // return address
|
||||
.D64(0x00007400c0005510ULL) // return address
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004001ULL;
|
||||
raw_context.rip = 0x00007400c0004001ULL;
|
||||
raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value
|
||||
CheckWalk();
|
||||
}
|
||||
@ -754,9 +855,9 @@ TEST_F(CFI, At4002) {
|
||||
Label frame1_rsp = expected.rsp;
|
||||
stack_section
|
||||
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
|
||||
.D64(0x40000000c0005510ULL) // return address
|
||||
.D64(0x00007400c0005510ULL) // return address
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004002ULL;
|
||||
raw_context.rip = 0x00007400c0004002ULL;
|
||||
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
|
||||
raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value
|
||||
CheckWalk();
|
||||
@ -769,9 +870,9 @@ TEST_F(CFI, At4003) {
|
||||
.D64(0x1d20ad8acacbe930ULL) // saved %r13
|
||||
.D64(0x319e68b49e3ace0fULL) // garbage
|
||||
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
|
||||
.D64(0x40000000c0005510ULL) // return address
|
||||
.D64(0x00007400c0005510ULL) // return address
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004003ULL;
|
||||
raw_context.rip = 0x00007400c0004003ULL;
|
||||
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
|
||||
raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
|
||||
raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
|
||||
@ -786,9 +887,9 @@ TEST_F(CFI, At4004) {
|
||||
.D64(0x1d20ad8acacbe930ULL) // saved %r13
|
||||
.D64(0x319e68b49e3ace0fULL) // garbage
|
||||
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
|
||||
.D64(0x40000000c0005510ULL) // return address
|
||||
.D64(0x00007400c0005510ULL) // return address
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004004ULL;
|
||||
raw_context.rip = 0x00007400c0004004ULL;
|
||||
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
|
||||
raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
|
||||
raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
|
||||
@ -804,10 +905,10 @@ TEST_F(CFI, At4005) {
|
||||
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
|
||||
.D64(0xaa95fa054aedfbaeULL) // garbage
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004005ULL;
|
||||
raw_context.rip = 0x00007400c0004005ULL;
|
||||
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
|
||||
raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12
|
||||
raw_context.r13 = 0x40000000c0005510ULL; // return address
|
||||
raw_context.r13 = 0x00007400c0005510ULL; // return address
|
||||
CheckWalk();
|
||||
}
|
||||
|
||||
@ -822,10 +923,10 @@ TEST_F(CFI, At4006) {
|
||||
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
|
||||
.D64(0xf015ee516ad89eabULL) // garbage
|
||||
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
|
||||
raw_context.rip = 0x40000000c0004006ULL;
|
||||
raw_context.rip = 0x00007400c0004006ULL;
|
||||
raw_context.rbp = frame0_rbp.Value();
|
||||
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
|
||||
raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12
|
||||
raw_context.r13 = 0x40000000c0005510ULL; // return address
|
||||
raw_context.r13 = 0x00007400c0005510ULL; // return address
|
||||
CheckWalk();
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ class TestValidMap : public ::testing::Test {
|
||||
|
||||
void TearDown() {
|
||||
for (int i = 0;i < kNumberTestCases; ++i)
|
||||
delete map_data[i];
|
||||
::operator delete(map_data[i]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/stdio.h"
|
||||
#include "common/stdio_wrapper.h"
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
#include "google_breakpad/common/minidump_exception_win32.h"
|
||||
#include "processor/symbolic_constants_win.h"
|
||||
|
37
src/processor/testdata/microdump-mips32.dmp
vendored
Normal file
37
src/processor/testdata/microdump-mips32.dmp
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
F/google-breakpad(11976): -----BEGIN BREAKPAD MICRODUMP-----
|
||||
F/google-breakpad(11976): V UNKNOWN:0.0.0.0
|
||||
F/google-breakpad(11976): O A mips 02 mips 3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015
|
||||
F/google-breakpad(11976): G UNKNOWN
|
||||
F/google-breakpad(11976): S 0 7F92FC38 7F92F000 00002000
|
||||
F/google-breakpad(11976): S 7F92F000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F92F180 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F92F300 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C801007701000000880140770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094020077010000008801407700000000880200770100000088014077000000005043BD770000000099999999000000000500000000000000030000000945BA7791F4927F0000000090F8927F90F4927F5043BD7700F8927F000000005432B67790F4927F00000000
|
||||
F/google-breakpad(11976): S 7F92F480 18000077000000005043BD77000000003100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF000000005043BD77000000009402B877FFFFFFFF0000400000004000000040000456B2774041C177000000005043BD7700000000FFFFFFFF9402B87700000000000000005043BD77C000407700000077700FB877000040006805B877E02FBA7700000000C8C6BA77000000005043BD77000000009402B877EC0EB877D02F007723000000C0004077FC0300000030B7770487B7775043BD77044BBF779402B8770000000000000000010000005043BD7700000000020000000000000000000077040000005043BD7754D2BC771E000000E00C4077
|
||||
F/google-breakpad(11976): S 7F92F600 D02F007701000000C0004077FC0300000030B7770487B777C0004077FC0300000030B7770487B77700000000010000005043BD770030B777000000000000000000000077370000000100000054D2BC770200000060024077C8004077888BB77717000000400A4077C8004077888BB7770100000054D2BC775043BD77A00140771000000000700377007003000030B777C00040772865BD775043BD77FC8CB777C0004077020000000070037780000000C00040772865BD77286AB77760024077C80040774CA4B777286AB777400A4077C80040774CA4B7775043BD7794D2BC770010000060300077C0004077020000005043BD77000000008001407702000000180000000000000028700377DCB0B77700000000000000000000000024AAB7775043BD7780D2BC7750300077180000000004000080D2BC77B8F7927F8C37BD7778D2BC77A0F8927F5043BD773C7EB9775043BD77B8F7927F9837BD779C37BD77B8F7927F8C37BD7778D2BC77A0F8927FE87BBC77307DB9770300000000000000
|
||||
F/google-breakpad(11976): S 7F92F780 5043BD77FF00000028700377000400005043BD77B8F7927F8C37BD77E03ABD7798A4BA770000000070A7BA7784A6BA7700000000A8A8BA77E87BBC776090B67702000000A0F8927FE03ABD770445BA77A4F9927FA0F9927F7CD2BC77E87BBC7728A6BF7778F5B5778004000000040000A4F9927FF4E0B5775043BD77F844BA77A0F8927F070000005043BD770400BC77A0F8927F070000005043BD77E03ABD775043BD77D0F4B577E03ABD7788EEB5775043BD77E03ABD7700000000E03ABD775043BD7700000000A002007701000000880140770445BA77A4F9927F64DCB3775043BD770000000002000000A0F8927F5043BD770445BA77A4F9927F02000000A0F8927F5426B2779402B877FFFFFFFFA0F9927FA4F9927F5043BD770456B277736F667469727100313736373431313720302032363138303938203020313436D002007701000000880140773431383020313136383631335043BD772031333136373332504E00775043BD77C000000000000000040000000000000000000000
|
||||
F/google-breakpad(11976): S 7F92F900 0000000024AAB777302030203020302030203020302032335043BD7720302030203020382865BD774000000000010000800000000030BD77504E00771800000050000000004E007702000000100000007CD2BC77E87BBC7728A6BF772C60B9772030203020302030020000000030BD7700000000000000005043BD776CD2BC7740000000DCDEB877203020302030203020302030203020305043BD7720302000010000008CD2BC775043BD77010000005043BD77000000005043BD770030BD77008D4077400000000030BD770030BD770030BD77E4F9B777A8C8B877F0C2B1775043BD770030BD775043BD77010000005043BD770000000000000000C000407768D2BC7770D2BC7702000000C4CFB877FCD185095043BD775043BD77FCD185095043BD7758F1B177C0004077144FB177D02F007701000000C0004077FC0300000030B7770487B77707000000AC50B17700000000B452C07700000000010000005043BD77B866B177040000000000000000000077380000000100000054D2BC77
|
||||
F/google-breakpad(11976): S 7F92FA80 0100000000024077C8004077888BB7770300000060CDC0775043BD7788C2BE770100000003000000D02F007704000000C0004077FC0300000030B7770487B777C00040772865BD775043BD77FC8CB77700000000010000005043BD77400000005043BD770400000000400000204E00775043BD7700000000000000000400000000000000000000000000000024AAB7770010000030D9BE7704000000040000005043BD7700024077009003772865BD7700000000000000000000000000000000204E00770800000020000000004E00770000000000000000EC17C87700E0C77700E0C7772C60B9774489B7770100000000000000588AB77700000000000000005043BD770800000000000000DCDEB8775043BD7701000000400D4077004000005043BD77009003770000000048B7B7775043BD770450C0775043BD77DCDEB877080000080020C177A80600002090C877040000000100000054FC927F0400000000E0C77784CBC177B00DC177C011BF772090C877000000000800000830800377
|
||||
F/google-breakpad(11976): S 7F92FC00 000000003828C17700000000000000002472C376E4FC927F5043BD775014C177E4FC927F004000005014C17700E0C77700E0C7778C2BC177C4FC927FC4FC927FC4FC927FC4FC927F2090C877C4FC927FC4FC927FEC10C17700000000E4FD927F010000006C11C1772090C8772472C3760100000000000000E86A98771012C177B0FC927FA821C77700000000000000000000000001000000FFFFFFFF080000002090C8770090BE7700500200E4FD927F03000000FFFFFFFF00000000000000000000000000000000000000000000000014000000FFFFFFFF000000000000000000000000000000006C0FC177000000000000000003000000FFFFFFFF00000000000000000000000000000000000000000000000000000000FFFFFFFF00000000000000000000000000000000030000000400000034FD927F34FD927F0000000040FD927F40FD927F0000000013AD8CAFECFD927F6465B177010000000000000000000000000000005043BD778B0000000100000060C7C077FFFFFFFFE86A9877
|
||||
F/google-breakpad(11976): S 7F92FD80 00E09677500EC1771C40C07700000000F0FB927F0090C0772090C877CCEDBE77480DC877500DC877580DC877600DC877680DC87700E0967701000000DC0DC1770100000000000000E86A987764B1BE7700000000000000000000000000000000010000007E0B937F000000008E0B937FA00B937FB30B937FD60B937FE10B937FFC0B937F070C937F1E0C937F370C937F4B0C937F640C937FE30C937FFD0C937FB90E937FCE0E937FE10E937F0D0F937F370F937F470F937F510F937F8E0F937FAD0F937FC20F937F000000001000000000000000060000000010000011000000640000000300000034E0C0770400000020000000050000000B000000070000000090BE77080000000000000009000000B00DC1770B000000000000000C000000000000000D000000000000000E00000000000000170000000000000019000000D8FE927F1F000000EC0F937F00000000000000000000000013AD8CAF8ABDF68B3A80A7E02317024E000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F92FF00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930080 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930200 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930380 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930500 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930680 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930800 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930980 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): S 7F930B00 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E2F63726173685F6578616D706C65005F3D2E2F63726173685F6578616D706C6500414E44524F49445F444154413D2F64617461005345434F4E444152595F53544F524147453D2F73746F726167652F7364636172643100484F4D453D2F6461746100414E44524F49445F4153534554533D2F73797374656D2F617070005445524D3D767431303000414E44524F49445F534F434B45545F616462643D313000414E44524F49445F53544F524147453D2F73746F72616765004D4B53483D2F73797374656D2F62696E2F7368004C4F4F505F4D4F554E54504F494E543D2F6D6E742F6F62620053595354454D534552564552434C415353504154483D2F7379737465
|
||||
F/google-breakpad(11976): S 7F930C80 6D2F6672616D65776F726B2F73657276696365732E6A61723A2F73797374656D2F6672616D65776F726B2F65746865726E65742D736572766963652E6A61723A2F73797374656D2F6672616D65776F726B2F776966692D736572766963652E6A617200415345435F4D4F554E54504F494E543D2F6D6E742F6173656300424F4F54434C415353504154483D2F73797374656D2F6672616D65776F726B2F636F72652D6C69626172742E6A61723A2F73797374656D2F6672616D65776F726B2F636F6E7363727970742E6A61723A2F73797374656D2F6672616D65776F726B2F6F6B687474702E6A61723A2F73797374656D2F6672616D65776F726B2F636F72652D6A756E69742E6A61723A2F73797374656D2F6672616D65776F726B2F626F756E6379636173746C652E6A61723A2F73797374656D2F6672616D65776F726B2F6578742E6A61723A2F73797374656D2F6672616D65776F726B2F6672616D65776F726B2E6A61723A2F73797374656D2F6672616D65776F726B2F74656C657068
|
||||
F/google-breakpad(11976): S 7F930E00 6F6E792D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F766F69702D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F696D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F6D6D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F616E64726F69642E706F6C6963792E6A61723A2F73797374656D2F6672616D65776F726B2F6170616368652D786D6C2E6A6172005348454C4C3D2F73797374656D2F62696E2F736800414E44524F49445F424F4F544C4F474F3D3100454D554C415445445F53544F524147455F534F555243453D2F6D6E742F7368656C6C2F656D756C6174656400454D554C415445445F53544F524147455F5441524745543D2F73746F726167652F656D756C6174656400484F53544E414D453D6E706D38303100555345523D726F6F7400504154483D2F7362696E3A2F76656E646F722F62696E3A2F73797374656D2F7362696E3A2F73797374656D2F62696E
|
||||
F/google-breakpad(11976): S 7F930F80 3A2F73797374656D2F7862696E00414E44524F49445F50524F50455254595F574F524B53504143453D382C3000414E44524F49445F524F4F543D2F73797374656D0045585445524E414C5F53544F524147453D2F73746F726167652F656D756C617465642F6C6567616379002E2F63726173685F6578616D706C650000000000
|
||||
F/google-breakpad(11976): C 0E0004000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006830007700000000683000770000000068300077000000002865BD770000000000000000000000002870037700000000284400000000000000000000000000003044000000000000ECFD927F00000000E4FD927F0000000001000000000000006C11C1770000000001000000000000002472C376000000000100000000000000000000000000000001000000000000005810C17700000000000000000000000000000000000000002090C8770000000038FC927F00000000E86A987700000000EC10C177000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000007C10C1770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
F/google-breakpad(11976): M 77C0E000 00000000 0006D000 8F36148CC4647A8116CAF2A25F591F570 crash_example
|
||||
F/google-breakpad(11976): M 77A9B000 00000000 00012000 3A1A14AAD5B1EB3BC54F2E1C36CE3ACB0 libnetd_client.so
|
||||
F/google-breakpad(11976): M 77ACD000 00000000 00012000 E8FC3CD6F45E059AD5849A4BEE176D0F0 libstdc++.so
|
||||
F/google-breakpad(11976): M 77ADF000 00000000 00024000 07C6570597295683DE36D8FE97E6AEC30 libm.so
|
||||
F/google-breakpad(11976): M 77B03000 00000000 000CB000 D1E0DFA8390BAADD25564F8B0E139FF90 libc.so
|
||||
F/google-breakpad(11976): M 77BD7000 00000000 00012000 EC0B4DDBEFC52282C34AF60EEEB8EAAA0 liblog.so
|
||||
F/google-breakpad(11976): M 77BE9000 00000000 00014000 8C70B1BF8FBAC1170EB21E350AB2E7580 linker
|
||||
F/google-breakpad(11976): -----END BREAKPAD MICRODUMP-----
|
||||
|
26
src/processor/testdata/microdump-mips64.dmp
vendored
Normal file
26
src/processor/testdata/microdump-mips64.dmp
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
02-23 15:49:14.700 1740 1739 F google-breakpad: -----BEGIN BREAKPAD MICRODUMP-----
|
||||
02-23 15:49:14.700 1740 1739 F google-breakpad: V UNKNOWN:0.0.0.0
|
||||
02-23 15:49:14.702 1740 1739 F google-breakpad: O A mips64 01 mips64 3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015
|
||||
02-23 15:49:14.702 1740 1739 F google-breakpad: G UNKNOWN
|
||||
02-23 15:49:14.702 1740 1739 F google-breakpad: S 0 000000FFFFCCF650 000000FFFFCCF000 0000000000001000
|
||||
02-23 15:49:14.707 1740 1739 F google-breakpad: S 000000FFFFCCF000 FF0000000000000000301DF1FF00000040701DF1FF0000008C7216F1FF000000704F1DF1FF00000000301DF1FF000000604F1DF1FF000000E0511DF1FF00000040701DF1FF0000001C2E16F1FF00000080501DF1FF000000A04F1DF1FF00000090501DF1FF000000E0511DF1FF000000C08416F1FF0000000000000000000000B0501DF1FF000000C08416F1FF0000000000000000000000C0501DF1FF000000C08416F1FF000000000000000000000008521DF1FF000000C08416F1FF0000000000000000000000F8511DF1FF000000C08416F1FF000000000000000000000000000000000000001000F5F0FF0000001000F5F0FF0000001000F5F0FF0000000800F5F0FF0000000010F5F0FF00000001000000000000000010F5F0FF0000000010F5F0FF0000000800F5F0FF0000000010F5F0FF0000000800F5F0FF0000000010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000800F5F0FF0000000010F5F0FF000000
|
||||
02-23 15:49:14.708 1740 1739 F google-breakpad: S 000000FFFFCCF180 0010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000800F5F0FF000000306042F1FF00000018F4CCFFFF00000018F4CCFFFF0000001010F5F0FF000000306042F1FF000000000000000000000018F4CCFFFF00000018F4CCFFFF000000000000000000000018F4CCFFFF0000000000000000000000000000000000000020F4CCFFFF00000000000000000000000010F5F0FF00000020F4CCFFFF0000000010F5F0FF00000020F4CCFFFF0000000810F5F0FF00000028F4CCFFFF0000000810F5F0FF00000028F4CCFFFF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF00000018F4CCFFFF00000030F4CCFFFF00000030F4CCFFFF0000001010F5F0FF00000030F4CCFFFF0000001010F5F0FF00000030F4CCFFFF0000000010F5F0FF0000000010F5F0FF000000306042F1FF00000060DF38F1FF000000A8F4CCFFFF0000000010F5F0FF0000000040000000000000880000000000000078462EF1FF000000D06B28F1FF000000
|
||||
02-23 15:49:14.710 1740 1739 F google-breakpad: S 000000FFFFCCF300 01000000000000001010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000010F5F0FF000000FFFFFFFFFFFFFF1F0010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF000000000000000000000018F4CCFFFF00000000F3CCFFFF00000018F4CCFFFF00000000F3CCFFFF0000000010F5F0FF0000000800F5F0FF000000A8F4CCFFFF0000001010F5F0FF0000000800F5F0FF000000A8F4CCFFFF000000A8F4CCFFFF0000001010F5F0FF0000000800F5F0FF000000A8F4CCFFFF000000A8F4CCFFFF0000001010F5F0FF0000000800F5F0FF000000A8F4CCFFFF000000A8F4CCFFFF00000008000000000000000800F5F0FF00000000000000000000000000000000000000000000000000000000000000000000001010F5F0FF00000078F8CCFFFF00000088F8CCFFFF000000306042F1FF00000024BB38F1FF000000FFFFFFFF0100000000000000000000005CA138F1FF0000000000000000000000
|
||||
02-23 15:49:14.711 1740 1739 F google-breakpad: S 000000FFFFCCF480 A8F6CCFFFF00000008F7CCFFFF000000404538F1FF000000344E33F1FF0000004B3838F1FF00000008F7CCFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF000000A8F7CCFFFF000000A8F7CCFFFF000000A8F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000C0F7CCFFFF000000C0F7CCFFFF000000C0F7CCFFFF0000000010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF000000389732F1FF000000E09432F1FF00000011000000000000001900000000000000389432F1FF0000007C9432F1FF000000
|
||||
02-23 15:49:14.713 1740 1739 F google-breakpad: S 000000FFFFCCF600 50C537F1FF000000C8F6CCFFFF0000000000000000000000C8F6CCFFFF000000D100000003000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF0000000000000000000000306042F1FF000000B0A238F1FF00000078F8CCFFFF0000000000000000000000306042F1FF000000B0A338F1FF00000078F8CCFFFF0000000000000001000000000000000000000003000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000005CA138F1FF0000000000000000000000000000000000000003000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000
|
||||
02-23 15:49:14.715 1740 1739 F google-breakpad: S 000000FFFFCCF780 00000000000000000000000000000000030000000400000098F7CCFFFF00000098F7CCFFFF0000000000000000000000B0F7CCFFFF000000B0F7CCFFFF0000000000000000000000EF89807E722BAE6F0820BAECFF00000078F8CCFFFF00000080462EF1FF000000ACBB1FF1FF00000008D537F1FF000000FFFFFFFFFFFFFFFF06261800000000000020B8ECFF000000306042F1FF0000003CA038F1FF000000D8DC41F1FF000000E8DC41F1FF000000F8DC41F1FF00000048C472ECFF000000306042F1FF000000D09F38F1FF0000000626180000000000443333F1FF000000404538F1FF000000000000000000000001000000000000000AFCCCFFFF00000000000000000000001AFCCCFFFF0000002CFCCCFFFF0000003FFCCCFFFF00000053FCCCFFFF0000005EFCCCFFFF00000068FCCCFFFF0000007DFCCCFFFF00000088FCCCFFFF0000009DFCCCFFFF000000B0FCCCFFFF000000C7FCCCFFFF000000E2FCCCFFFF0000008AFECCFFFF000000A4FECCFFFF000000BBFECCFFFF000000
|
||||
02-23 15:49:14.716 1740 1739 F google-breakpad: S 000000FFFFCCF900 D3FECCFFFF000000F4FECCFFFF0000000DFFCCFFFF0000004AFFCCFFFF000000C9FFCCFFFF00000000000000000000001000000000000000030000000000000006000000000000000010000000000000110000000000000064000000000000000300000000000000402038F1FF0000000400000000000000380000000000000005000000000000000B000000000000000700000000000000009032F1FF000000080000000000000000000000000000000900000000000000A09F38F1FF0000000B0000000000000000000000000000000C0000000000000000000000000000000D0000000000000000000000000000000E00000000000000000000000000000017000000000000000000000000000000190000000000000040FACCFFFF0000001F00000000000000E8FFCCFFFF00000000000000000000000000000000000000EF89807E722BAE6F9B236B56712BD221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
02-23 15:49:14.717 1740 1739 F google-breakpad: S 000000FFFFCCFA80 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
02-23 15:49:14.719 1740 1739 F google-breakpad: S 000000FFFFCCFC00 000000000000000000002E2F63726173685F6578616D706C65005F3D2E2F63726173685F6578616D706C6500414E44524F49445F444154413D2F64617461004D4B53483D2F73797374656D2F62696E2F736800484F4D453D2F6461746100555345523D726F6F7400414E44524F49445F524F4F543D2F73797374656D005445524D3D787465726D005348454C4C3D2F73797374656D2F62696E2F736800414E44524F49445F424F4F544C4F474F3D3100544D504449523D2F646174612F6C6F63616C2F746D7000414E44524F49445F4153534554533D2F73797374656D2F61707000424F4F54434C415353504154483D2F73797374656D2F6672616D65776F726B2F636F72652D6C69626172742E6A61723A2F73797374656D2F6672616D65776F726B2F636F6E7363727970742E6A61723A2F73797374656D2F6672616D65776F726B2F6F6B687474702E6A61723A2F73797374656D2F6672616D65776F726B2F636F72652D6A756E69742E6A61723A2F73797374656D2F6672616D65776F72
|
||||
02-23 15:49:14.720 1740 1739 F google-breakpad: S 000000FFFFCCFD80 6B2F626F756E6379636173746C652E6A61723A2F73797374656D2F6672616D65776F726B2F6578742E6A61723A2F73797374656D2F6672616D65776F726B2F6672616D65776F726B2E6A61723A2F73797374656D2F6672616D65776F726B2F74656C6570686F6E792D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F766F69702D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F696D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F6170616368652D786D6C2E6A61723A2F73797374656D2F6672616D65776F726B2F6F72672E6170616368652E687474702E6C65676163792E626F6F742E6A617200415345435F4D4F554E54504F494E543D2F6D6E742F6173656300414E44524F49445F534F434B45545F616462643D313000484F53544E414D453D67656E657269635F6D69707336340045585445524E414C5F53544F524147453D2F73746F726167652F73646361726400414E44524F49445F53544F52
|
||||
02-23 15:49:14.720 1740 1739 F google-breakpad: S 000000FFFFCCFF00 4147453D2F73746F7261676500504154483D2F7362696E3A2F76656E646F722F62696E3A2F73797374656D2F7362696E3A2F73797374656D2F62696E3A2F73797374656D2F7862696E0053595354454D534552564552434C415353504154483D2F73797374656D2F6672616D65776F726B2F73657276696365732E6A61723A2F73797374656D2F6672616D65776F726B2F65746865726E65742D736572766963652E6A61723A2F73797374656D2F6672616D65776F726B2F776966692D736572766963652E6A617200414E44524F49445F50524F50455254595F574F524B53504143453D392C30002E2F63726173685F6578616D706C65000000000000000000
|
||||
02-23 15:49:14.723 1740 1739 F google-breakpad: C 0E000800000000000000000000000000010000000000000000000000000000000100000000000000000000000000000038F241F1FF0000000000FFFFFFFFFFFF0000000000000000FFFF000000000000FCFFFFFFFFFFFFFF00000000000000000100000000000000010000000000000000000000000000000100000000000000010000000000000078F8CCFFFF00000088F8CCFFFF00000001000000000000001CA338F1FF00000000001000000000000820BAECFF00000048C472ECFF0000000000000000000000000000000000000028A238F1FF00000010000000000000000000000000000000306042F1FF00000050F6CCFFFF0000000626180000000000B0A238F1FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004CA238F1FF00000000000000000000000000000000000000FFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7F0000000000000000
|
||||
02-23 15:49:14.725 1740 1739 F google-breakpad: M 000000FFF1382000 0000000000000000 0000000000081000 6E72E2F1A5F59AB3D51356FDFE394D490 crash_example
|
||||
02-23 15:49:14.725 1740 1739 F google-breakpad: M 000000FFF0FE2000 0000000000000000 0000000000014000 3C1F908C8C62D8A2EBFC12D8AF285F670 libnetd_client.so
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1016000 0000000000000000 000000000005D000 F53A8A43C039FF5DB65F78E97ADAAE000 libm.so
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1073000 0000000000000000 0000000000014000 906759235C65BD24385BA1376F1C4A0D0 libstdc++.so
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1083000 0000000000000000 0000000000150000 FF1D9D1DA2F0B636817320E78C3E2AF20 libc++.so
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF11D6000 0000000000000000 0000000000109000 3A55BF92DE1E4C51F6F6140479CFA5080 libc.so
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF12ED000 0000000000000000 000000000001C000 44F1FB3127301036FA2EFE040F09CF6C0 liblog.so
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1329000 0000000000000000 000000000003A000 519DF595D6558C61E962693B460A31C80 linker64
|
||||
02-23 15:49:14.726 1740 1739 F google-breakpad: -----END BREAKPAD MICRODUMP-----
|
@ -0,0 +1,56 @@
|
||||
MODULE Linux mips 6E72E2F1A5F59AB3D51356FDFE394D490 crash_example
|
||||
FILE 0 /s/breakpad/src/tools/linux/crash_example.cc
|
||||
FUNC 80a8 9c 0 google_breakpad::MinidumpDescriptor::MinidumpDescriptor
|
||||
80a8 20 75 8
|
||||
80c8 38 78 8
|
||||
8100 10 78 8
|
||||
8110 14 78 8
|
||||
8124 10 78 8
|
||||
8134 10 78 8
|
||||
FUNC 815c a0 0 DumpCallback
|
||||
815c 2c 13 37
|
||||
8188 1c 14 37
|
||||
81a4 14 15 37
|
||||
81b8 1c 15 37
|
||||
81d4 14 17 37
|
||||
81e8 4 18 37
|
||||
81ec 10 19 37
|
||||
FUNC 81fc 2c 0 Leaf
|
||||
81fc 10 21 37
|
||||
820c 8 22 37
|
||||
8214 8 23 37
|
||||
821c 4 25 37
|
||||
8220 8 26 37
|
||||
FUNC 8228 58 0 blaTest
|
||||
8228 1c 28 37
|
||||
8244 c 29 37
|
||||
8250 20 30 37
|
||||
8270 10 31 37
|
||||
FUNC 8280 40 0 Crash
|
||||
8280 18 33 37
|
||||
8298 4 34 37
|
||||
829c 14 35 37
|
||||
82b0 10 36 37
|
||||
FUNC 831c f4 0 main
|
||||
831c 2c 40 37
|
||||
8348 c 40 37
|
||||
8354 18 41 37
|
||||
836c 34 43 37
|
||||
83a0 10 44 37
|
||||
83b0 4 45 37
|
||||
83b4 14 43 37
|
||||
83c8 18 45 37
|
||||
83e0 30 46 37
|
||||
PUBLIC 831c 0 main
|
||||
STACK CFI INIT 8228 58 .cfa: $sp 0 + .ra: $ra
|
||||
STACK CFI 822c .cfa: $sp 32 +
|
||||
STACK CFI 8234 $gp: .cfa -16 + ^ .ra: .cfa -8 + ^
|
||||
STACK CFI 827c $gp: $gp .cfa: $sp 0 + .ra: .ra
|
||||
STACK CFI INIT 8280 40 .cfa: $sp 0 + .ra: $ra
|
||||
STACK CFI 8284 .cfa: $sp 32 +
|
||||
STACK CFI 828c $gp: .cfa -16 + ^ .ra: .cfa -8 + ^
|
||||
STACK CFI 82bc $gp: $gp .cfa: $sp 0 + .ra: .ra
|
||||
STACK CFI INIT 831c f4 .cfa: $sp 0 + .ra: $ra
|
||||
STACK CFI 8320 .cfa: $sp 352 +
|
||||
STACK CFI 832c $gp: .cfa -16 + ^ $s0: .cfa -24 + ^ .ra: .cfa -8 + ^
|
||||
STACK CFI 840c $gp: $gp $s0: $s0 .cfa: $sp 0 + .ra: .ra
|
@ -0,0 +1,48 @@
|
||||
MODULE Linux mips 8F36148CC4647A8116CAF2A25F591F570 crash_example
|
||||
FILE 0 /home/rtrk/chromium_mips/chromium/src/out-android-mips/Debug/../../breakpad/src/tools/linux/crash_example.cc
|
||||
FUNC 2ea4 b4 0 google_breakpad::MinidumpDescriptor::MinidumpDescriptor
|
||||
2ea4 20 75 6
|
||||
2ec4 40 78 6
|
||||
2f04 18 78 6
|
||||
2f1c 14 78 6
|
||||
2f30 18 78 6
|
||||
2f48 10 78 6
|
||||
FUNC 2f6c c4 0 DumpCallback
|
||||
2f6c 28 13 33
|
||||
2f94 28 14 33
|
||||
2fbc 1c 15 33
|
||||
2fd8 28 15 33
|
||||
3000 1c 17 33
|
||||
301c 4 18 33
|
||||
3020 10 19 33
|
||||
FUNC 3030 28 0 Leaf
|
||||
3030 4 21 33
|
||||
3034 c 22 33
|
||||
3040 c 23 33
|
||||
304c 4 25 33
|
||||
3050 8 26 33
|
||||
FUNC 3058 60 0 blaTest
|
||||
3058 1c 28 33
|
||||
3074 c 29 33
|
||||
3080 28 30 33
|
||||
30a8 10 31 33
|
||||
FUNC 30b8 48 0 Crash
|
||||
30b8 18 33 33
|
||||
30d0 4 34 33
|
||||
30d4 1c 35 33
|
||||
30f0 10 36 33
|
||||
FUNC 316c 120 0 main
|
||||
316c 24 40 33
|
||||
3190 c 40 33
|
||||
319c 20 41 33
|
||||
31bc 40 43 33
|
||||
31fc 18 44 33
|
||||
3214 4 45 33
|
||||
3218 1c 43 33
|
||||
3234 20 45 33
|
||||
3254 38 46 33
|
||||
PUBLIC 316c 0 main
|
||||
STACK CFI INIT 30b8 48 .cfa: $sp 39792944 + .ra: $ra
|
||||
STACK CFI 30c8 .cfa: $sp 40 +
|
||||
STACK CFI 30d0 .ra: .cfa -4 + ^
|
||||
STACK CFI 30f8 .cfa: $sp 0 + .ra: .ra
|
@ -118,7 +118,7 @@ struct WindowsFrameInfo {
|
||||
uint64_t &code_size) {
|
||||
// The format of a STACK WIN record is documented at:
|
||||
//
|
||||
// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
|
||||
// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
|
||||
|
||||
std::vector<char> buffer;
|
||||
StringToVector(string, buffer);
|
||||
|
163
src/third_party/musl/COPYRIGHT
vendored
Normal file
163
src/third_party/musl/COPYRIGHT
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
musl as a whole is licensed under the following standard MIT license:
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Copyright © 2005-2014 Rich Felker, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Authors/contributors include:
|
||||
|
||||
Alex Dowad
|
||||
Alexander Monakov
|
||||
Anthony G. Basile
|
||||
Arvid Picciani
|
||||
Bobby Bingham
|
||||
Boris Brezillon
|
||||
Brent Cook
|
||||
Chris Spiegel
|
||||
Clément Vasseur
|
||||
Daniel Micay
|
||||
Denys Vlasenko
|
||||
Emil Renner Berthing
|
||||
Felix Fietkau
|
||||
Felix Janda
|
||||
Gianluca Anzolin
|
||||
Hauke Mehrtens
|
||||
Hiltjo Posthuma
|
||||
Isaac Dunham
|
||||
Jaydeep Patil
|
||||
Jens Gustedt
|
||||
Jeremy Huntwork
|
||||
Jo-Philipp Wich
|
||||
Joakim Sindholt
|
||||
John Spencer
|
||||
Josiah Worcester
|
||||
Justin Cormack
|
||||
Khem Raj
|
||||
Kylie McClain
|
||||
Luca Barbato
|
||||
Luka Perkov
|
||||
M Farkas-Dyck (Strake)
|
||||
Mahesh Bodapati
|
||||
Michael Forney
|
||||
Natanael Copa
|
||||
Nicholas J. Kain
|
||||
orc
|
||||
Pascal Cuoq
|
||||
Petr Hosek
|
||||
Pierre Carrier
|
||||
Rich Felker
|
||||
Richard Pennington
|
||||
Shiz
|
||||
sin
|
||||
Solar Designer
|
||||
Stefan Kristiansson
|
||||
Szabolcs Nagy
|
||||
Timo Teräs
|
||||
Trutz Behn
|
||||
Valentin Ochs
|
||||
William Haddon
|
||||
|
||||
Portions of this software are derived from third-party works licensed
|
||||
under terms compatible with the above MIT license:
|
||||
|
||||
The TRE regular expression implementation (src/regex/reg* and
|
||||
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
|
||||
under a 2-clause BSD license (license text in the source files). The
|
||||
included version has been heavily modified by Rich Felker in 2012, in
|
||||
the interests of size, simplicity, and namespace cleanliness.
|
||||
|
||||
Much of the math library code (src/math/* and src/complex/*) is
|
||||
Copyright © 1993,2004 Sun Microsystems or
|
||||
Copyright © 2003-2011 David Schultz or
|
||||
Copyright © 2003-2009 Steven G. Kargl or
|
||||
Copyright © 2003-2009 Bruce D. Evans or
|
||||
Copyright © 2008 Stephen L. Moshier
|
||||
and labelled as such in comments in the individual source files. All
|
||||
have been licensed under extremely permissive terms.
|
||||
|
||||
The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
|
||||
The Android Open Source Project and is licensed under a two-clause BSD
|
||||
license. It was taken from Bionic libc, used on Android.
|
||||
|
||||
The implementation of DES for crypt (src/crypt/crypt_des.c) is
|
||||
Copyright © 1994 David Burren. It is licensed under a BSD license.
|
||||
|
||||
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
|
||||
originally written by Solar Designer and placed into the public
|
||||
domain. The code also comes with a fallback permissive license for use
|
||||
in jurisdictions that may not recognize the public domain.
|
||||
|
||||
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
|
||||
Valentin Ochs and is licensed under an MIT-style license.
|
||||
|
||||
The BSD PRNG implementation (src/prng/random.c) and XSI search API
|
||||
(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
|
||||
licensed under following terms: "Permission to use, copy, modify,
|
||||
and/or distribute this code for any purpose with or without fee is
|
||||
hereby granted. There is no warranty."
|
||||
|
||||
The x86_64 port was written by Nicholas J. Kain and is licensed under
|
||||
the standard MIT terms.
|
||||
|
||||
The mips and microblaze ports were originally written by Richard
|
||||
Pennington for use in the ellcc project. The original code was adapted
|
||||
by Rich Felker for build system and code conventions during upstream
|
||||
integration. It is licensed under the standard MIT terms.
|
||||
|
||||
The mips64 port was contributed by Imagination Technologies and is
|
||||
licensed under the standard MIT terms.
|
||||
|
||||
The powerpc port was also originally written by Richard Pennington,
|
||||
and later supplemented and integrated by John Spencer. It is licensed
|
||||
under the standard MIT terms.
|
||||
|
||||
All other files which have no copyright comments are original works
|
||||
produced specifically for use as part of this library, written either
|
||||
by Rich Felker, the main author of the library, or by one or more
|
||||
contibutors listed above. Details on authorship of individual files
|
||||
can be found in the git version control history of the project. The
|
||||
omission of copyright and license comments in each file is in the
|
||||
interest of source tree size.
|
||||
|
||||
In addition, permission is hereby granted for all public header files
|
||||
(include/* and arch/*/bits/*) and crt files intended to be linked into
|
||||
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
|
||||
the copyright notice and permission notice otherwise required by the
|
||||
license, and to use these files without any requirement of
|
||||
attribution. These files include substantial contributions from:
|
||||
|
||||
Bobby Bingham
|
||||
John Spencer
|
||||
Nicholas J. Kain
|
||||
Rich Felker
|
||||
Richard Pennington
|
||||
Stefan Kristiansson
|
||||
Szabolcs Nagy
|
||||
|
||||
all of whom have explicitly granted such permission.
|
||||
|
||||
This file previously contained text expressing a belief that most of
|
||||
the files covered by the above exception were sufficiently trivial not
|
||||
to be subject to copyright, resulting in confusion over whether it
|
||||
negated the permissions granted in the license. In the spirit of
|
||||
permissive licensing, and of not having licensing issues being an
|
||||
obstacle to adoption, that text has been removed.
|
23
src/third_party/musl/README
vendored
Normal file
23
src/third_party/musl/README
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
musl libc
|
||||
|
||||
musl, pronounced like the word "mussel", is an MIT-licensed
|
||||
implementation of the standard C library targetting the Linux syscall
|
||||
API, suitable for use in a wide range of deployment environments. musl
|
||||
offers efficient static and dynamic linking support, lightweight code
|
||||
and low runtime overhead, strong fail-safe guarantees under correct
|
||||
usage, and correctness in the sense of standards conformance and
|
||||
safety. musl is built on the principle that these goals are best
|
||||
achieved through simple code that is easy to understand and maintain.
|
||||
|
||||
The 1.1 release series for musl features coverage for all interfaces
|
||||
defined in ISO C99 and POSIX 2008 base, along with a number of
|
||||
non-standardized interfaces for compatibility with Linux, BSD, and
|
||||
glibc functionality.
|
||||
|
||||
For basic installation instructions, see the included INSTALL file.
|
||||
Information on full musl-targeted compiler toolchains, system
|
||||
bootstrapping, and Linux distributions built on musl can be found on
|
||||
the project website:
|
||||
|
||||
http://www.musl-libc.org/
|
3
src/third_party/musl/README.breakpad
vendored
Normal file
3
src/third_party/musl/README.breakpad
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
This directory contains the elf header from
|
||||
https://git.musl-libc.org/cgit/musl/tree/
|
||||
that is required to get ELF working in dump_syms on Mac OS X.
|
1
src/third_party/musl/VERSION
vendored
Normal file
1
src/third_party/musl/VERSION
vendored
Normal file
@ -0,0 +1 @@
|
||||
1.1.14
|
2827
src/third_party/musl/include/elf.h
vendored
Normal file
2827
src/third_party/musl/include/elf.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -39,11 +39,13 @@
|
||||
#include "common/linux/dump_symbols.h"
|
||||
|
||||
using google_breakpad::WriteSymbolFile;
|
||||
using google_breakpad::WriteSymbolFileHeader;
|
||||
|
||||
int usage(const char* self) {
|
||||
fprintf(stderr, "Usage: %s [OPTION] <binary-with-debugging-info> "
|
||||
"[directories-for-debug-file]\n\n", self);
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -i: Output module header information only.\n");
|
||||
fprintf(stderr, " -c Do not generate CFI section\n");
|
||||
fprintf(stderr, " -r Do not handle inter-compilation unit references\n");
|
||||
fprintf(stderr, " -v Print all warnings to stderr\n");
|
||||
@ -53,27 +55,29 @@ int usage(const char* self) {
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2)
|
||||
return usage(argv[0]);
|
||||
|
||||
bool header_only = false;
|
||||
bool cfi = true;
|
||||
bool handle_inter_cu_refs = true;
|
||||
bool log_to_stderr = false;
|
||||
int arg_index = 1;
|
||||
while (arg_index < argc && strlen(argv[arg_index]) > 0 &&
|
||||
argv[arg_index][0] == '-') {
|
||||
if (strcmp("-c", argv[arg_index]) == 0) {
|
||||
if (strcmp("-i", argv[arg_index]) == 0) {
|
||||
header_only = true;
|
||||
} else if (strcmp("-c", argv[arg_index]) == 0) {
|
||||
cfi = false;
|
||||
} else if (strcmp("-r", argv[arg_index]) == 0) {
|
||||
handle_inter_cu_refs = false;
|
||||
} else if (strcmp("-v", argv[arg_index]) == 0) {
|
||||
log_to_stderr = true;
|
||||
} else {
|
||||
printf("2.4 %s\n", argv[arg_index]);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
++arg_index;
|
||||
}
|
||||
if (arg_index == argc)
|
||||
return usage(argv[0]);
|
||||
|
||||
// Save stderr so it can be used below.
|
||||
FILE* saved_stderr = fdopen(dup(fileno(stderr)), "w");
|
||||
if (!log_to_stderr) {
|
||||
@ -82,7 +86,6 @@ int main(int argc, char **argv) {
|
||||
// Add this brace section to silence gcc warnings.
|
||||
}
|
||||
}
|
||||
|
||||
const char* binary;
|
||||
std::vector<string> debug_dirs;
|
||||
binary = argv[arg_index];
|
||||
@ -92,11 +95,18 @@ int main(int argc, char **argv) {
|
||||
debug_dirs.push_back(argv[debug_dir_index]);
|
||||
}
|
||||
|
||||
SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI;
|
||||
google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs);
|
||||
if (!WriteSymbolFile(binary, debug_dirs, options, std::cout)) {
|
||||
fprintf(saved_stderr, "Failed to write symbol file.\n");
|
||||
return 1;
|
||||
if (header_only) {
|
||||
if (!WriteSymbolFileHeader(binary, std::cout)) {
|
||||
fprintf(saved_stderr, "Failed to process file.\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI;
|
||||
google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs);
|
||||
if (!WriteSymbolFile(binary, debug_dirs, options, std::cout)) {
|
||||
fprintf(saved_stderr, "Failed to write symbol file.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -39,138 +39,13 @@
|
||||
// cpu: the CPU that the module was built for
|
||||
// symbol_file: the contents of the breakpad-format symbol file
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/linux/symbol_upload.h"
|
||||
|
||||
#include "common/linux/http_upload.h"
|
||||
#include "common/using_std_string.h"
|
||||
|
||||
using google_breakpad::HTTPUpload;
|
||||
|
||||
typedef struct {
|
||||
string symbolsPath;
|
||||
string uploadURLStr;
|
||||
string proxy;
|
||||
string proxy_user_pwd;
|
||||
string version;
|
||||
bool success;
|
||||
} Options;
|
||||
|
||||
static void TokenizeByChar(const string &source_string,
|
||||
int c, std::vector<string> *results) {
|
||||
assert(results);
|
||||
string::size_type cur_pos = 0, next_pos = 0;
|
||||
while ((next_pos = source_string.find(c, cur_pos)) != string::npos) {
|
||||
if (next_pos != cur_pos)
|
||||
results->push_back(source_string.substr(cur_pos, next_pos - cur_pos));
|
||||
cur_pos = next_pos + 1;
|
||||
}
|
||||
if (cur_pos < source_string.size() && next_pos != cur_pos)
|
||||
results->push_back(source_string.substr(cur_pos));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Parse out the module line which have 5 parts.
|
||||
// MODULE <os> <cpu> <uuid> <module-name>
|
||||
static bool ModuleDataForSymbolFile(const string &file,
|
||||
std::vector<string> *module_parts) {
|
||||
assert(module_parts);
|
||||
const size_t kModulePartNumber = 5;
|
||||
FILE* fp = fopen(file.c_str(), "r");
|
||||
if (fp) {
|
||||
char buffer[1024];
|
||||
if (fgets(buffer, sizeof(buffer), fp)) {
|
||||
string line(buffer);
|
||||
string::size_type line_break_pos = line.find_first_of('\n');
|
||||
if (line_break_pos == string::npos) {
|
||||
assert(0 && "The file is invalid!");
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
line.resize(line_break_pos);
|
||||
const char kDelimiter = ' ';
|
||||
TokenizeByChar(line, kDelimiter, module_parts);
|
||||
if (module_parts->size() != kModulePartNumber)
|
||||
module_parts->clear();
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return module_parts->size() == kModulePartNumber;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
static string CompactIdentifier(const string &uuid) {
|
||||
std::vector<string> components;
|
||||
TokenizeByChar(uuid, '-', &components);
|
||||
string result;
|
||||
for (size_t i = 0; i < components.size(); ++i)
|
||||
result += components[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
static void Start(Options *options) {
|
||||
std::map<string, string> parameters;
|
||||
options->success = false;
|
||||
std::vector<string> module_parts;
|
||||
if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
|
||||
fprintf(stderr, "Failed to parse symbol file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
string compacted_id = CompactIdentifier(module_parts[3]);
|
||||
|
||||
// Add parameters
|
||||
if (!options->version.empty())
|
||||
parameters["version"] = options->version;
|
||||
|
||||
// MODULE <os> <cpu> <uuid> <module-name>
|
||||
// 0 1 2 3 4
|
||||
parameters["os"] = module_parts[1];
|
||||
parameters["cpu"] = module_parts[2];
|
||||
parameters["debug_file"] = module_parts[4];
|
||||
parameters["code_file"] = module_parts[4];
|
||||
parameters["debug_identifier"] = compacted_id;
|
||||
|
||||
std::map<string, string> files;
|
||||
files["symbol_file"] = options->symbolsPath;
|
||||
|
||||
string response, error;
|
||||
long response_code;
|
||||
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
|
||||
parameters,
|
||||
files,
|
||||
options->proxy,
|
||||
options->proxy_user_pwd,
|
||||
"",
|
||||
&response,
|
||||
&response_code,
|
||||
&error);
|
||||
|
||||
if (!success) {
|
||||
printf("Failed to send symbol file: %s\n", error.c_str());
|
||||
printf("Response code: %ld\n", response_code);
|
||||
printf("Response:\n");
|
||||
printf("%s\n", response.c_str());
|
||||
} else if (response_code == 0) {
|
||||
printf("Failed to send symbol file: No response code\n");
|
||||
} else if (response_code != 200) {
|
||||
printf("Failed to send symbol file: Response code %ld\n", response_code);
|
||||
printf("Response:\n");
|
||||
printf("%s\n", response.c_str());
|
||||
} else {
|
||||
printf("Successfully sent the symbol file.\n");
|
||||
}
|
||||
options->success = success;
|
||||
}
|
||||
using google_breakpad::sym_upload::Options;
|
||||
|
||||
//=============================================================================
|
||||
static void
|
||||
@ -232,6 +107,6 @@ SetupOptions(int argc, const char *argv[], Options *options) {
|
||||
int main(int argc, const char* argv[]) {
|
||||
Options options;
|
||||
SetupOptions(argc, argv, &options);
|
||||
Start(&options);
|
||||
google_breakpad::sym_upload::Start(&options);
|
||||
return options.success ? 0 : 1;
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
|
||||
162F6500161C5F2200CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
|
||||
4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D72CAF413DFBAC2006CABE3 /* md5.cc */; };
|
||||
8BCAAA4C1CE3A7980046090B /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */; };
|
||||
8BCAAA4D1CE3B1260046090B /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */; };
|
||||
B84A91F8116CF78F006C210E /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
|
||||
B84A91FB116CF7AF006C210E /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
|
||||
B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3C11666C8900407530 /* stabs_to_module.cc */; };
|
||||
@ -280,6 +282,8 @@
|
||||
8B31023E11F0CF1C00FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8BCAAA4A1CE3A7980046090B /* elf_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = elf_reader.cc; path = ../../../common/dwarf/elf_reader.cc; sourceTree = "<group>"; };
|
||||
8BCAAA4B1CE3A7980046090B /* elf_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = elf_reader.h; path = ../../../common/dwarf/elf_reader.h; sourceTree = "<group>"; };
|
||||
9BDF186D0B1BB43700F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = "<group>"; };
|
||||
9BDF186E0B1BB43700F8391B /* dump_syms_tool.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dump_syms_tool.cc; sourceTree = "<group>"; };
|
||||
9BE650410B52F6D800611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
|
||||
@ -613,6 +617,8 @@
|
||||
B88FAE1711665FE400407530 /* dwarf2diehandler.cc */,
|
||||
B88FAE1811665FE400407530 /* dwarf2diehandler.h */,
|
||||
B88FB0DB116CEC5800407530 /* dwarf2diehandler_unittest.cc */,
|
||||
8BCAAA4A1CE3A7980046090B /* elf_reader.cc */,
|
||||
8BCAAA4B1CE3A7980046090B /* elf_reader.h */,
|
||||
);
|
||||
name = DWARF;
|
||||
sourceTree = "<group>";
|
||||
@ -887,6 +893,8 @@
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
@ -954,6 +962,7 @@
|
||||
files = (
|
||||
B88FAF38116A595400407530 /* dwarf2reader_cfi_unittest.cc in Sources */,
|
||||
B88FAF3F116A5A2E00407530 /* dwarf2reader.cc in Sources */,
|
||||
8BCAAA4D1CE3B1260046090B /* elf_reader.cc in Sources */,
|
||||
B88FAF40116A5A2E00407530 /* bytereader.cc in Sources */,
|
||||
B88FAF37116A595400407530 /* cfi_assembler.cc in Sources */,
|
||||
);
|
||||
@ -1071,6 +1080,7 @@
|
||||
files = (
|
||||
162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */,
|
||||
B88FAE2C1166606200407530 /* macho_reader.cc in Sources */,
|
||||
8BCAAA4C1CE3A7980046090B /* elf_reader.cc in Sources */,
|
||||
B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */,
|
||||
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */,
|
||||
B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */,
|
||||
@ -1225,7 +1235,11 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ../../..;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../..,
|
||||
../../../common/mac/include/,
|
||||
../../../third_party/musl/include/,
|
||||
);
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -1233,7 +1247,11 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ../../..;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../..,
|
||||
../../../common/mac/include/,
|
||||
../../../third_party/musl/include/,
|
||||
);
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@ -1619,7 +1637,6 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
|
||||
GCC_VERSION = "";
|
||||
PRODUCT_NAME = dump_syms;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -1629,7 +1646,6 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
|
||||
GCC_VERSION = "";
|
||||
PRODUCT_NAME = dump_syms;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -51,11 +51,13 @@ using std::vector;
|
||||
|
||||
struct Options {
|
||||
Options()
|
||||
: srcPath(), dsymPath(), arch(), cfi(true), handle_inter_cu_refs(true) {}
|
||||
: srcPath(), dsymPath(), arch(), header_only(false),
|
||||
cfi(true), handle_inter_cu_refs(true) {}
|
||||
|
||||
string srcPath;
|
||||
string dsymPath;
|
||||
const NXArchInfo *arch;
|
||||
bool header_only;
|
||||
bool cfi;
|
||||
bool handle_inter_cu_refs;
|
||||
};
|
||||
@ -151,6 +153,9 @@ static bool Start(const Options &options) {
|
||||
}
|
||||
}
|
||||
|
||||
if (options.header_only)
|
||||
return dump_symbols.WriteSymbolFileHeader(std::cout);
|
||||
|
||||
// Read the primary file into a Breakpad Module.
|
||||
Module* module = NULL;
|
||||
if (!dump_symbols.ReadSymbolData(&module))
|
||||
@ -189,6 +194,7 @@ static void Usage(int argc, const char *argv[]) {
|
||||
fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
|
||||
fprintf(stderr, "Usage: %s [-a ARCHITECTURE] [-c] [-g dSYM path] "
|
||||
"<Mach-o file>\n", argv[0]);
|
||||
fprintf(stderr, "\t-i: Output module header information only.\n");
|
||||
fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
|
||||
fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
|
||||
fprintf(stderr, "\t-g: Debug symbol file (dSYM) to dump in addition to the "
|
||||
@ -204,8 +210,11 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
|
||||
extern int optind;
|
||||
signed char ch;
|
||||
|
||||
while ((ch = getopt(argc, (char * const *)argv, "a:g:chr?")) != -1) {
|
||||
while ((ch = getopt(argc, (char * const *)argv, "ia:g:chr?")) != -1) {
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
options->header_only = true;
|
||||
break;
|
||||
case 'a': {
|
||||
const NXArchInfo *arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromName(optarg);
|
||||
|
@ -54,7 +54,7 @@ class SymbolFileParser(object):
|
||||
"""Parser for Breakpad symbol files.
|
||||
|
||||
The format of these files is documented at
|
||||
https://code.google.com/p/google-breakpad/wiki/SymbolFiles
|
||||
https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
|
||||
"""
|
||||
|
||||
def __init__(self, input_stream, output_stream, ignored_prefixes=None,
|
||||
|
Loading…
Reference in New Issue
Block a user