mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
4540 lines
197 KiB
Diff
4540 lines
197 KiB
Diff
# HG changeset patch
|
|
# User Ted Mielczarek <ted.mielczarek@gmail.com>
|
|
# Date 1360255134 18000
|
|
# Thu Feb 07 11:38:54 2013 -0500
|
|
# Node ID 79cecfef3c2a10d719fe1af9fae2e5257109b028
|
|
# Parent 08f184a7e6d6d15ecc20abd56bc4e36669c0c68a
|
|
Rework PostfixEvaluator to use a UniqueString type
|
|
Patch by Julian Seward <jseward@acm.org>, R=ted
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -134,16 +134,17 @@
|
|
src/google_breakpad/processor/source_line_resolver_interface.h \
|
|
src/google_breakpad/processor/stack_frame.h \
|
|
src/google_breakpad/processor/stack_frame_cpu.h \
|
|
src/google_breakpad/processor/stack_frame_symbolizer.h \
|
|
src/google_breakpad/processor/stackwalker.h \
|
|
src/google_breakpad/processor/symbol_supplier.h \
|
|
src/google_breakpad/processor/system_info.h \
|
|
src/common/module.cc \
|
|
+ src/common/unique_string.cc \
|
|
src/processor/address_map-inl.h \
|
|
src/processor/address_map.h \
|
|
src/processor/basic_code_module.h \
|
|
src/processor/basic_code_modules.cc \
|
|
src/processor/basic_code_modules.h \
|
|
src/processor/basic_source_line_resolver_types.h \
|
|
src/processor/basic_source_line_resolver.cc \
|
|
src/processor/binarystream.h \
|
|
@@ -430,16 +431,17 @@
|
|
src_tools_linux_dump_syms_dump_syms_SOURCES = \
|
|
src/common/dwarf_cfi_to_module.cc \
|
|
src/common/dwarf_cu_to_module.cc \
|
|
src/common/dwarf_line_to_module.cc \
|
|
src/common/language.cc \
|
|
src/common/module.cc \
|
|
src/common/stabs_reader.cc \
|
|
src/common/stabs_to_module.cc \
|
|
+ src/common/unique_string.cc \
|
|
src/common/dwarf/bytereader.cc \
|
|
src/common/dwarf/dwarf2diehandler.cc \
|
|
src/common/dwarf/dwarf2reader.cc \
|
|
src/common/linux/dump_symbols.cc \
|
|
src/common/linux/elf_symbols_to_module.cc \
|
|
src/common/linux/elfutils.cc \
|
|
src/common/linux/file_id.cc \
|
|
src/common/linux/linux_libc_support.cc \
|
|
@@ -473,16 +475,17 @@
|
|
src/common/memory_range_unittest.cc \
|
|
src/common/module.cc \
|
|
src/common/module_unittest.cc \
|
|
src/common/stabs_reader.cc \
|
|
src/common/stabs_reader_unittest.cc \
|
|
src/common/stabs_to_module.cc \
|
|
src/common/stabs_to_module_unittest.cc \
|
|
src/common/test_assembler.cc \
|
|
+ src/common/unique_string.cc \
|
|
src/common/dwarf/bytereader.cc \
|
|
src/common/dwarf/bytereader_unittest.cc \
|
|
src/common/dwarf/cfi_assembler.cc \
|
|
src/common/dwarf/dwarf2diehandler.cc \
|
|
src/common/dwarf/dwarf2diehandler_unittest.cc \
|
|
src/common/dwarf/dwarf2reader.cc \
|
|
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
|
|
src/common/dwarf/dwarf2reader_die_unittest.cc \
|
|
@@ -561,31 +564,33 @@
|
|
src_processor_basic_source_line_resolver_unittest_CPPFLAGS = \
|
|
-I$(top_srcdir)/src \
|
|
-I$(top_srcdir)/src/testing/include \
|
|
-I$(top_srcdir)/src/testing/gtest/include \
|
|
-I$(top_srcdir)/src/testing/gtest \
|
|
-I$(top_srcdir)/src/testing
|
|
src_processor_basic_source_line_resolver_unittest_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/basic_source_line_resolver.o \
|
|
src/processor/cfi_frame_info.o \
|
|
src/processor/pathname_stripper.o \
|
|
src/processor/logging.o \
|
|
src/processor/source_line_resolver_base.o \
|
|
src/processor/tokenize.o \
|
|
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
src_processor_cfi_frame_info_unittest_SOURCES = \
|
|
src/processor/cfi_frame_info_unittest.cc \
|
|
src/testing/gtest/src/gtest-all.cc \
|
|
src/testing/gtest/src/gtest_main.cc \
|
|
src/testing/src/gmock-all.cc
|
|
src_processor_cfi_frame_info_unittest_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/cfi_frame_info.o \
|
|
src/processor/logging.o \
|
|
src/processor/pathname_stripper.o \
|
|
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
src_processor_cfi_frame_info_unittest_CPPFLAGS = \
|
|
-I$(top_srcdir)/src \
|
|
-I$(top_srcdir)/src/testing/include \
|
|
-I$(top_srcdir)/src/testing/gtest/include \
|
|
@@ -606,16 +611,17 @@
|
|
src_processor_exploitability_unittest_CPPFLAGS = \
|
|
-I$(top_srcdir)/src \
|
|
-I$(top_srcdir)/src/testing/include \
|
|
-I$(top_srcdir)/src/testing/gtest/include \
|
|
-I$(top_srcdir)/src/testing/gtest \
|
|
-I$(top_srcdir)/src/testing
|
|
src_processor_exploitability_unittest_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/minidump_processor.o \
|
|
src/processor/process_state.o \
|
|
src/processor/disassembler_x86.o \
|
|
src/processor/exploitability.o \
|
|
src/processor/exploitability_win.o \
|
|
src/processor/basic_code_modules.o \
|
|
src/processor/basic_source_line_resolver.o \
|
|
src/processor/call_stack.o \
|
|
@@ -659,16 +665,17 @@
|
|
src_processor_fast_source_line_resolver_unittest_CPPFLAGS = \
|
|
-I$(top_srcdir)/src \
|
|
-I$(top_srcdir)/src/testing/include \
|
|
-I$(top_srcdir)/src/testing/gtest/include \
|
|
-I$(top_srcdir)/src/testing/gtest \
|
|
-I$(top_srcdir)/src/testing
|
|
src_processor_fast_source_line_resolver_unittest_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/fast_source_line_resolver.o \
|
|
src/processor/basic_source_line_resolver.o \
|
|
src/processor/cfi_frame_info.o \
|
|
src/processor/module_comparer.o \
|
|
src/processor/module_serializer.o \
|
|
src/processor/pathname_stripper.o \
|
|
src/processor/logging.o \
|
|
src/processor/source_line_resolver_base.o \
|
|
@@ -697,16 +704,17 @@
|
|
src_processor_minidump_processor_unittest_CPPFLAGS = \
|
|
-I$(top_srcdir)/src \
|
|
-I$(top_srcdir)/src/testing/include \
|
|
-I$(top_srcdir)/src/testing/gtest/include \
|
|
-I$(top_srcdir)/src/testing/gtest \
|
|
-I$(top_srcdir)/src/testing
|
|
src_processor_minidump_processor_unittest_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/basic_code_modules.o \
|
|
src/processor/basic_source_line_resolver.o \
|
|
src/processor/call_stack.o \
|
|
src/processor/cfi_frame_info.o \
|
|
src/processor/disassembler_x86.o \
|
|
src/processor/exploitability.o \
|
|
src/processor/exploitability_win.o \
|
|
src/processor/logging.o \
|
|
@@ -812,16 +820,17 @@
|
|
src_processor_pathname_stripper_unittest_LDADD = \
|
|
src/processor/pathname_stripper.o \
|
|
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
src_processor_postfix_evaluator_unittest_SOURCES = \
|
|
src/processor/postfix_evaluator_unittest.cc
|
|
src_processor_postfix_evaluator_unittest_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/logging.o \
|
|
src/processor/pathname_stripper.o \
|
|
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
src_processor_range_map_unittest_SOURCES = \
|
|
src/processor/range_map_unittest.cc
|
|
src_processor_range_map_unittest_LDADD = \
|
|
src/processor/logging.o \
|
|
@@ -943,16 +952,17 @@
|
|
src/processor/logging.o \
|
|
src/processor/minidump.o \
|
|
src/processor/pathname_stripper.o
|
|
|
|
src_processor_minidump_stackwalk_SOURCES = \
|
|
src/processor/minidump_stackwalk.cc
|
|
src_processor_minidump_stackwalk_LDADD = \
|
|
src/common/module.o \
|
|
+ src/common/unique_string.o \
|
|
src/processor/basic_code_modules.o \
|
|
src/processor/basic_source_line_resolver.o \
|
|
src/processor/binarystream.o \
|
|
src/processor/call_stack.o \
|
|
src/processor/cfi_frame_info.o \
|
|
src/processor/disassembler_x86.o \
|
|
src/processor/exploitability.o \
|
|
src/processor/exploitability_win.o \
|
|
diff --git a/Makefile.in b/Makefile.in
|
|
--- a/Makefile.in
|
|
+++ b/Makefile.in
|
|
@@ -267,18 +267,19 @@
|
|
src/google_breakpad/processor/source_line_resolver_base.h \
|
|
src/google_breakpad/processor/source_line_resolver_interface.h \
|
|
src/google_breakpad/processor/stack_frame.h \
|
|
src/google_breakpad/processor/stack_frame_cpu.h \
|
|
src/google_breakpad/processor/stack_frame_symbolizer.h \
|
|
src/google_breakpad/processor/stackwalker.h \
|
|
src/google_breakpad/processor/symbol_supplier.h \
|
|
src/google_breakpad/processor/system_info.h \
|
|
- src/common/module.cc src/processor/address_map-inl.h \
|
|
- src/processor/address_map.h src/processor/basic_code_module.h \
|
|
+ src/common/module.cc src/common/unique_string.cc \
|
|
+ src/processor/address_map-inl.h src/processor/address_map.h \
|
|
+ src/processor/basic_code_module.h \
|
|
src/processor/basic_code_modules.cc \
|
|
src/processor/basic_code_modules.h \
|
|
src/processor/basic_source_line_resolver_types.h \
|
|
src/processor/basic_source_line_resolver.cc \
|
|
src/processor/binarystream.h src/processor/binarystream.cc \
|
|
src/processor/call_stack.cc src/processor/cfi_frame_info.cc \
|
|
src/processor/cfi_frame_info.h \
|
|
src/processor/contained_range_map-inl.h \
|
|
@@ -332,16 +333,17 @@
|
|
src/processor/static_map_iterator-inl.h \
|
|
src/processor/static_map_iterator.h \
|
|
src/processor/static_map-inl.h src/processor/static_map.h \
|
|
src/processor/static_range_map-inl.h \
|
|
src/processor/static_range_map.h src/processor/tokenize.cc \
|
|
src/processor/tokenize.h
|
|
@DISABLE_PROCESSOR_FALSE@am_src_libbreakpad_a_OBJECTS = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.$(OBJEXT) \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.$(OBJEXT) \
|
|
@@ -525,17 +527,18 @@
|
|
src/common/dwarf_cu_to_module_unittest.cc \
|
|
src/common/dwarf_line_to_module.cc \
|
|
src/common/dwarf_line_to_module_unittest.cc \
|
|
src/common/language.cc src/common/memory_range_unittest.cc \
|
|
src/common/module.cc src/common/module_unittest.cc \
|
|
src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \
|
|
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/test_assembler.cc src/common/unique_string.cc \
|
|
+ src/common/dwarf/bytereader.cc \
|
|
src/common/dwarf/bytereader_unittest.cc \
|
|
src/common/dwarf/cfi_assembler.cc \
|
|
src/common/dwarf/dwarf2diehandler.cc \
|
|
src/common/dwarf/dwarf2diehandler_unittest.cc \
|
|
src/common/dwarf/dwarf2reader.cc \
|
|
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
|
|
src/common/dwarf/dwarf2reader_die_unittest.cc \
|
|
src/common/linux/dump_symbols.cc \
|
|
@@ -569,16 +572,17 @@
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT) \
|
|
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-unique_string.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-cfi_assembler.$(OBJEXT) \
|
|
@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-dwarf2reader_cfi_unittest.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \
|
|
@@ -637,16 +641,17 @@
|
|
src/testing/gtest/src/gtest-all.cc \
|
|
src/testing/src/gmock-all.cc
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_basic_source_line_resolver_unittest_OBJECTS = src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_basic_source_line_resolver_unittest-gtest-all.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_basic_source_line_resolver_unittest-gmock-all.$(OBJEXT)
|
|
src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_basic_source_line_resolver_unittest_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
|
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
|
|
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
|
|
@@ -671,16 +676,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_cfi_frame_info_unittest_OBJECTS = src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_cfi_frame_info_unittest-gtest-all.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_cfi_frame_info_unittest-gtest_main.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_cfi_frame_info_unittest-gmock-all.$(OBJEXT)
|
|
src_processor_cfi_frame_info_unittest_OBJECTS = \
|
|
$(am_src_processor_cfi_frame_info_unittest_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
|
|
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
|
|
am__src_processor_contained_range_map_unittest_SOURCES_DIST = \
|
|
src/processor/contained_range_map_unittest.cc
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_contained_range_map_unittest_OBJECTS = src/processor/contained_range_map_unittest.$(OBJEXT)
|
|
@@ -713,16 +719,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_exploitability_unittest_OBJECTS = src/processor/src_processor_exploitability_unittest-exploitability_unittest.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_exploitability_unittest-gtest-all.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_exploitability_unittest-gtest_main.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_exploitability_unittest-gmock-all.$(OBJEXT)
|
|
src_processor_exploitability_unittest_OBJECTS = \
|
|
$(am_src_processor_exploitability_unittest_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
|
|
@@ -748,16 +755,17 @@
|
|
src/testing/gtest/src/gtest-all.cc \
|
|
src/testing/src/gmock-all.cc
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_fast_source_line_resolver_unittest_OBJECTS = src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.$(OBJEXT)
|
|
src_processor_fast_source_line_resolver_unittest_OBJECTS = $(am_src_processor_fast_source_line_resolver_unittest_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
|
@@ -794,16 +802,17 @@
|
|
src/testing/src/gmock-all.cc
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_processor_unittest_OBJECTS = src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT) \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT)
|
|
src_processor_minidump_processor_unittest_OBJECTS = \
|
|
$(am_src_processor_minidump_processor_unittest_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@@ -826,16 +835,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
|
|
am__src_processor_minidump_stackwalk_SOURCES_DIST = \
|
|
src/processor/minidump_stackwalk.cc
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_stackwalk_OBJECTS = src/processor/minidump_stackwalk.$(OBJEXT)
|
|
src_processor_minidump_stackwalk_OBJECTS = \
|
|
$(am_src_processor_minidump_stackwalk_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
|
|
@@ -889,16 +899,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
|
|
am__src_processor_postfix_evaluator_unittest_SOURCES_DIST = \
|
|
src/processor/postfix_evaluator_unittest.cc
|
|
@DISABLE_PROCESSOR_FALSE@am_src_processor_postfix_evaluator_unittest_OBJECTS = src/processor/postfix_evaluator_unittest.$(OBJEXT)
|
|
src_processor_postfix_evaluator_unittest_OBJECTS = \
|
|
$(am_src_processor_postfix_evaluator_unittest_OBJECTS)
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_DEPENDENCIES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@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)
|
|
src_processor_range_map_unittest_OBJECTS = \
|
|
@@ -1069,33 +1080,35 @@
|
|
src_tools_linux_core2md_core2md_OBJECTS = \
|
|
$(am_src_tools_linux_core2md_core2md_OBJECTS)
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_DEPENDENCIES = src/client/linux/libbreakpad_client.a
|
|
am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
|
|
src/common/dwarf_cfi_to_module.cc \
|
|
src/common/dwarf_cu_to_module.cc \
|
|
src/common/dwarf_line_to_module.cc src/common/language.cc \
|
|
src/common/module.cc src/common/stabs_reader.cc \
|
|
- src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
|
|
+ src/common/stabs_to_module.cc src/common/unique_string.cc \
|
|
+ src/common/dwarf/bytereader.cc \
|
|
src/common/dwarf/dwarf2diehandler.cc \
|
|
src/common/dwarf/dwarf2reader.cc \
|
|
src/common/linux/dump_symbols.cc \
|
|
src/common/linux/elf_symbols_to_module.cc \
|
|
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 \
|
|
src/common/linux/safe_readlink.cc \
|
|
src/tools/linux/dump_syms/dump_syms.cc
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_dump_syms_dump_syms_OBJECTS = src/common/dwarf_cfi_to_module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.$(OBJEXT) \
|
|
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/unique_string.$(OBJEXT) \
|
|
@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/linux/dump_symbols.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.$(OBJEXT) \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.$(OBJEXT) \
|
|
@@ -1416,16 +1429,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_interface.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_cpu.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_symbolizer.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stackwalker.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/symbol_supplier.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/system_info.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.cc \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.cc \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/address_map-inl.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/address_map.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_module.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.cc \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_types.h \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.cc \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.h \
|
|
@@ -1618,16 +1632,17 @@
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_dump_syms_dump_syms_SOURCES = \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \
|
|
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/unique_string.cc \
|
|
@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/linux/dump_symbols.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
|
|
@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 \
|
|
@@ -1661,16 +1676,17 @@
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module_unittest.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader_unittest.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \
|
|
@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/unique_string.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
|
|
@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/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_cfi_unittest.cc \
|
|
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \
|
|
@@ -1753,32 +1769,34 @@
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
|
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info_unittest.cc \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/gtest-all.cc \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/gtest_main.cc \
|
|
@DISABLE_PROCESSOR_FALSE@ src/testing/src/gmock-all.cc
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_CPPFLAGS = \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \
|
|
@@ -1803,16 +1821,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
|
|
@@ -1860,16 +1879,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
|
@@ -1902,16 +1922,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \
|
|
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@@ -2029,16 +2050,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_SOURCES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest.cc
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
|
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_SOURCES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest.cc
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_LDADD = \
|
|
@@ -2169,16 +2191,17 @@
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_SOURCES = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk.cc
|
|
|
|
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_LDADD = \
|
|
@DISABLE_PROCESSOR_FALSE@ src/common/module.o \
|
|
+@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
|
|
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
|
|
@@ -2527,16 +2550,18 @@
|
|
@$(MKDIR_P) src/client/linux
|
|
@: > src/client/linux/$(am__dirstamp)
|
|
src/client/linux/libbreakpad_client.a: $(src_client_linux_libbreakpad_client_a_OBJECTS) $(src_client_linux_libbreakpad_client_a_DEPENDENCIES) $(EXTRA_src_client_linux_libbreakpad_client_a_DEPENDENCIES) src/client/linux/$(am__dirstamp)
|
|
-rm -f src/client/linux/libbreakpad_client.a
|
|
$(src_client_linux_libbreakpad_client_a_AR) src/client/linux/libbreakpad_client.a $(src_client_linux_libbreakpad_client_a_OBJECTS) $(src_client_linux_libbreakpad_client_a_LIBADD)
|
|
$(RANLIB) src/client/linux/libbreakpad_client.a
|
|
src/common/module.$(OBJEXT): src/common/$(am__dirstamp) \
|
|
src/common/$(DEPDIR)/$(am__dirstamp)
|
|
+src/common/unique_string.$(OBJEXT): src/common/$(am__dirstamp) \
|
|
+ src/common/$(DEPDIR)/$(am__dirstamp)
|
|
src/processor/$(am__dirstamp):
|
|
@$(MKDIR_P) src/processor
|
|
@: > src/processor/$(am__dirstamp)
|
|
src/processor/$(DEPDIR)/$(am__dirstamp):
|
|
@$(MKDIR_P) src/processor/$(DEPDIR)
|
|
@: > src/processor/$(DEPDIR)/$(am__dirstamp)
|
|
src/processor/basic_code_modules.$(OBJEXT): \
|
|
src/processor/$(am__dirstamp) \
|
|
@@ -2863,16 +2888,19 @@
|
|
src/common/$(am__dirstamp) \
|
|
src/common/$(DEPDIR)/$(am__dirstamp)
|
|
src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT): \
|
|
src/common/$(am__dirstamp) \
|
|
src/common/$(DEPDIR)/$(am__dirstamp)
|
|
src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT): \
|
|
src/common/$(am__dirstamp) \
|
|
src/common/$(DEPDIR)/$(am__dirstamp)
|
|
+src/common/src_common_dumper_unittest-unique_string.$(OBJEXT): \
|
|
+ src/common/$(am__dirstamp) \
|
|
+ src/common/$(DEPDIR)/$(am__dirstamp)
|
|
src/common/dwarf/$(am__dirstamp):
|
|
@$(MKDIR_P) src/common/dwarf
|
|
@: > src/common/dwarf/$(am__dirstamp)
|
|
src/common/dwarf/$(DEPDIR)/$(am__dirstamp):
|
|
@$(MKDIR_P) src/common/dwarf/$(DEPDIR)
|
|
@: > src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
|
|
src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT): \
|
|
src/common/dwarf/$(am__dirstamp) \
|
|
@@ -3470,28 +3498,30 @@
|
|
-rm -f src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-module.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT)
|
|
-rm -f src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT)
|
|
+ -rm -f src/common/src_common_dumper_unittest-unique_string.$(OBJEXT)
|
|
-rm -f src/common/src_common_test_assembler_unittest-test_assembler.$(OBJEXT)
|
|
-rm -f src/common/src_common_test_assembler_unittest-test_assembler_unittest.$(OBJEXT)
|
|
-rm -f src/common/src_processor_minidump_unittest-test_assembler.$(OBJEXT)
|
|
-rm -f src/common/src_processor_stackwalker_amd64_unittest-test_assembler.$(OBJEXT)
|
|
-rm -f src/common/src_processor_stackwalker_arm_unittest-test_assembler.$(OBJEXT)
|
|
-rm -f src/common/src_processor_stackwalker_x86_unittest-test_assembler.$(OBJEXT)
|
|
-rm -f src/common/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT)
|
|
-rm -f src/common/stabs_reader.$(OBJEXT)
|
|
-rm -f src/common/stabs_to_module.$(OBJEXT)
|
|
-rm -f src/common/string_conversion.$(OBJEXT)
|
|
-rm -f src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.$(OBJEXT)
|
|
-rm -f src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT)
|
|
+ -rm -f src/common/unique_string.$(OBJEXT)
|
|
-rm -f src/processor/address_map_unittest.$(OBJEXT)
|
|
-rm -f src/processor/basic_code_modules.$(OBJEXT)
|
|
-rm -f src/processor/basic_source_line_resolver.$(OBJEXT)
|
|
-rm -f src/processor/binarystream.$(OBJEXT)
|
|
-rm -f src/processor/call_stack.$(OBJEXT)
|
|
-rm -f src/processor/cfi_frame_info.$(OBJEXT)
|
|
-rm -f src/processor/contained_range_map_unittest.$(OBJEXT)
|
|
-rm -f src/processor/disassembler_x86.$(OBJEXT)
|
|
@@ -3663,26 +3693,28 @@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po@am__quote@
|
|
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_reader.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_to_module.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/string_conversion.Po@am__quote@
|
|
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/unique_string.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/breakpad_getcontext.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po@am__quote@
|
|
@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)/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@
|
|
@@ -4474,16 +4506,30 @@
|
|
|
|
src/common/src_common_dumper_unittest-test_assembler.obj: src/common/test_assembler.cc
|
|
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Tpo -c -o src/common/src_common_dumper_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
|
|
@am__fastdepCXX_TRUE@ $(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po
|
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/test_assembler.cc' object='src/common/src_common_dumper_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
|
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
|
|
|
|
+src/common/src_common_dumper_unittest-unique_string.o: src/common/unique_string.cc
|
|
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-unique_string.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Tpo -c -o src/common/src_common_dumper_unittest-unique_string.o `test -f 'src/common/unique_string.cc' || echo '$(srcdir)/'`src/common/unique_string.cc
|
|
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Po
|
|
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/unique_string.cc' object='src/common/src_common_dumper_unittest-unique_string.o' libtool=no @AMDEPBACKSLASH@
|
|
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-unique_string.o `test -f 'src/common/unique_string.cc' || echo '$(srcdir)/'`src/common/unique_string.cc
|
|
+
|
|
+src/common/src_common_dumper_unittest-unique_string.obj: src/common/unique_string.cc
|
|
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-unique_string.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Tpo -c -o src/common/src_common_dumper_unittest-unique_string.obj `if test -f 'src/common/unique_string.cc'; then $(CYGPATH_W) 'src/common/unique_string.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/unique_string.cc'; fi`
|
|
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Po
|
|
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/unique_string.cc' object='src/common/src_common_dumper_unittest-unique_string.obj' libtool=no @AMDEPBACKSLASH@
|
|
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-unique_string.obj `if test -f 'src/common/unique_string.cc'; then $(CYGPATH_W) 'src/common/unique_string.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/unique_string.cc'; fi`
|
|
+
|
|
src/common/dwarf/src_common_dumper_unittest-bytereader.o: src/common/dwarf/bytereader.cc
|
|
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-bytereader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
|
|
@am__fastdepCXX_TRUE@ $(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po
|
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader.o' libtool=no @AMDEPBACKSLASH@
|
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
|
|
|
|
src/common/dwarf/src_common_dumper_unittest-bytereader.obj: src/common/dwarf/bytereader.cc
|
|
diff --git a/src/common/dwarf_cfi_to_module.cc b/src/common/dwarf_cfi_to_module.cc
|
|
--- a/src/common/dwarf_cfi_to_module.cc
|
|
+++ b/src/common/dwarf_cfi_to_module.cc
|
|
@@ -37,40 +37,44 @@
|
|
#include <sstream>
|
|
|
|
#include "common/dwarf_cfi_to_module.h"
|
|
|
|
namespace google_breakpad {
|
|
|
|
using std::ostringstream;
|
|
|
|
-vector<string> DwarfCFIToModule::RegisterNames::MakeVector(
|
|
- const char * const *strings,
|
|
+vector<const UniqueString*> DwarfCFIToModule::RegisterNames::MakeVector(
|
|
+ const char* const* strings,
|
|
size_t size) {
|
|
- vector<string> names(strings, strings + size);
|
|
+ vector<const UniqueString*> names(size, NULL);
|
|
+ for (size_t i = 0; i < size; ++i) {
|
|
+ names[i] = ToUniqueString(strings[i]);
|
|
+ }
|
|
+
|
|
return names;
|
|
}
|
|
|
|
-vector<string> DwarfCFIToModule::RegisterNames::I386() {
|
|
+vector<const UniqueString*> DwarfCFIToModule::RegisterNames::I386() {
|
|
static const char *const names[] = {
|
|
"$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
|
|
"$eip", "$eflags", "$unused1",
|
|
"$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
|
|
"$unused2", "$unused3",
|
|
"$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
|
|
"$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
|
|
"$fcw", "$fsw", "$mxcsr",
|
|
"$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
|
|
"$tr", "$ldtr"
|
|
};
|
|
|
|
return MakeVector(names, sizeof(names) / sizeof(names[0]));
|
|
}
|
|
|
|
-vector<string> DwarfCFIToModule::RegisterNames::X86_64() {
|
|
+vector<const UniqueString*> DwarfCFIToModule::RegisterNames::X86_64() {
|
|
static const char *const names[] = {
|
|
"$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
|
|
"$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
|
|
"$rip",
|
|
"$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
|
|
"$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
|
|
"$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
|
|
"$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
|
|
@@ -80,17 +84,17 @@
|
|
"$tr", "$ldtr",
|
|
"$mxcsr", "$fcw", "$fsw"
|
|
};
|
|
|
|
return MakeVector(names, sizeof(names) / sizeof(names[0]));
|
|
}
|
|
|
|
// Per ARM IHI 0040A, section 3.1
|
|
-vector<string> DwarfCFIToModule::RegisterNames::ARM() {
|
|
+vector<const UniqueString*> DwarfCFIToModule::RegisterNames::ARM() {
|
|
static const char *const names[] = {
|
|
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
|
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
|
|
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
|
"fps", "cpsr", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
@@ -122,40 +126,40 @@
|
|
return_address_ = return_address;
|
|
|
|
// Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
|
|
// may not establish any rule for .ra if the return address column
|
|
// is an ordinary register, and that register holds the return
|
|
// address on entry to the function. So establish an initial .ra
|
|
// rule citing the return address register.
|
|
if (return_address_ < register_names_.size())
|
|
- entry_->initial_rules[ra_name_]
|
|
+ entry_->initial_rules[ustr__ZDra()]
|
|
= Module::Expr(register_names_[return_address_], 0, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
-string DwarfCFIToModule::RegisterName(int i) {
|
|
+const UniqueString* DwarfCFIToModule::RegisterName(int i) {
|
|
assert(entry_);
|
|
if (i < 0) {
|
|
assert(i == kCFARegister);
|
|
- return cfa_name_;
|
|
+ return ustr__ZDcfa();
|
|
}
|
|
unsigned reg = i;
|
|
if (reg == return_address_)
|
|
- return ra_name_;
|
|
+ return ustr__ZDra();
|
|
|
|
// Ensure that a non-empty name exists for this register value.
|
|
- if (reg < register_names_.size() && !register_names_[reg].empty())
|
|
+ if (reg < register_names_.size() && register_names_[reg] != ustr__empty())
|
|
return register_names_[reg];
|
|
|
|
reporter_->UnnamedRegister(entry_offset_, reg);
|
|
char buf[30];
|
|
sprintf(buf, "unnamed_register%u", reg);
|
|
- return buf;
|
|
+ return ToUniqueString(buf);
|
|
}
|
|
|
|
void DwarfCFIToModule::Record(Module::Address address, int reg,
|
|
const Module::Expr &rule) {
|
|
assert(entry_);
|
|
|
|
// Is this one of this entry's initial rules?
|
|
if (address == entry_->address)
|
|
@@ -228,28 +232,30 @@
|
|
|
|
void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
|
|
fprintf(stderr, "%s, section '%s': "
|
|
"the call frame entry at offset 0x%zx refers to register %d,"
|
|
" whose name we don't know\n",
|
|
file_.c_str(), section_.c_str(), offset, reg);
|
|
}
|
|
|
|
-void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset,
|
|
- const string ®) {
|
|
+void DwarfCFIToModule::Reporter::UndefinedNotSupported(
|
|
+ size_t offset,
|
|
+ const UniqueString* reg) {
|
|
fprintf(stderr, "%s, section '%s': "
|
|
"the call frame entry at offset 0x%zx sets the rule for "
|
|
"register '%s' to 'undefined', but the Breakpad symbol file format"
|
|
" cannot express this\n",
|
|
- file_.c_str(), section_.c_str(), offset, reg.c_str());
|
|
+ file_.c_str(), section_.c_str(), offset, FromUniqueString(reg));
|
|
}
|
|
|
|
-void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset,
|
|
- const string ®) {
|
|
+void DwarfCFIToModule::Reporter::ExpressionsNotSupported(
|
|
+ size_t offset,
|
|
+ const UniqueString* reg) {
|
|
fprintf(stderr, "%s, section '%s': "
|
|
"the call frame entry at offset 0x%zx uses a DWARF expression to"
|
|
" describe how to recover register '%s', "
|
|
" but this translator cannot yet translate DWARF expressions to"
|
|
" Breakpad postfix expressions\n",
|
|
- file_.c_str(), section_.c_str(), offset, reg.c_str());
|
|
+ file_.c_str(), section_.c_str(), offset, FromUniqueString(reg));
|
|
}
|
|
|
|
} // namespace google_breakpad
|
|
diff --git a/src/common/dwarf_cfi_to_module.h b/src/common/dwarf_cfi_to_module.h
|
|
--- a/src/common/dwarf_cfi_to_module.h
|
|
+++ b/src/common/dwarf_cfi_to_module.h
|
|
@@ -44,16 +44,17 @@
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "common/module.h"
|
|
#include "common/dwarf/dwarf2reader.h"
|
|
#include "common/using_std_string.h"
|
|
+#include "common/unique_string.h"
|
|
|
|
namespace google_breakpad {
|
|
|
|
using dwarf2reader::CallFrameInfo;
|
|
using google_breakpad::Module;
|
|
using std::set;
|
|
using std::vector;
|
|
|
|
@@ -78,61 +79,65 @@
|
|
// The DWARF CFI entry at OFFSET cites register REG, but REG is not
|
|
// covered by the vector of register names passed to the
|
|
// DwarfCFIToModule constructor, nor does it match the return
|
|
// address column number for this entry.
|
|
virtual void UnnamedRegister(size_t offset, int reg);
|
|
|
|
// The DWARF CFI entry at OFFSET says that REG is undefined, but the
|
|
// Breakpad symbol file format cannot express this.
|
|
- virtual void UndefinedNotSupported(size_t offset, const string ®);
|
|
+ virtual void UndefinedNotSupported(size_t offset,
|
|
+ const UniqueString* reg);
|
|
|
|
// The DWARF CFI entry at OFFSET says that REG uses a DWARF
|
|
// expression to find its value, but DwarfCFIToModule is not
|
|
// capable of translating DWARF expressions to Breakpad postfix
|
|
// expressions.
|
|
- virtual void ExpressionsNotSupported(size_t offset, const string ®);
|
|
+ virtual void ExpressionsNotSupported(size_t offset,
|
|
+ const UniqueString* reg);
|
|
|
|
protected:
|
|
string file_, section_;
|
|
};
|
|
|
|
// Register name tables. If TABLE is a vector returned by one of these
|
|
// functions, then TABLE[R] is the name of the register numbered R in
|
|
// DWARF call frame information.
|
|
class RegisterNames {
|
|
public:
|
|
// Intel's "x86" or IA-32.
|
|
- static vector<string> I386();
|
|
+ static vector<const UniqueString*> I386();
|
|
|
|
// AMD x86_64, AMD64, Intel EM64T, or Intel 64
|
|
- static vector<string> X86_64();
|
|
+ static vector<const UniqueString*> X86_64();
|
|
|
|
// ARM.
|
|
- static vector<string> ARM();
|
|
+ static vector<const UniqueString*> ARM();
|
|
|
|
private:
|
|
// Given STRINGS, an array of C strings with SIZE elements, return an
|
|
// equivalent vector<string>.
|
|
- static vector<string> MakeVector(const char * const *strings, size_t size);
|
|
+ static vector<const UniqueString*> MakeVector(const char * const *strings,
|
|
+ size_t size);
|
|
};
|
|
|
|
// Create a handler for the dwarf2reader::CallFrameInfo parser that
|
|
// records the stack unwinding information it receives in MODULE.
|
|
//
|
|
// Use REGISTER_NAMES[I] as the name of register number I; *this
|
|
// keeps a reference to the vector, so the vector should remain
|
|
// alive for as long as the DwarfCFIToModule does.
|
|
//
|
|
// Use REPORTER for reporting problems encountered in the conversion
|
|
// process.
|
|
- DwarfCFIToModule(Module *module, const vector<string> ®ister_names,
|
|
+ DwarfCFIToModule(Module *module,
|
|
+ const vector<const UniqueString*> ®ister_names,
|
|
Reporter *reporter)
|
|
: module_(module), register_names_(register_names), reporter_(reporter),
|
|
- entry_(NULL), return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") {
|
|
+ entry_(NULL), return_address_(-1) {
|
|
}
|
|
virtual ~DwarfCFIToModule() { delete entry_; }
|
|
|
|
virtual bool Entry(size_t offset, uint64 address, uint64 length,
|
|
uint8 version, const string &augmentation,
|
|
unsigned return_address);
|
|
virtual bool UndefinedRule(uint64 address, int reg);
|
|
virtual bool SameValueRule(uint64 address, int reg);
|
|
@@ -144,53 +149,36 @@
|
|
virtual bool ExpressionRule(uint64 address, int reg,
|
|
const string &expression);
|
|
virtual bool ValExpressionRule(uint64 address, int reg,
|
|
const string &expression);
|
|
virtual bool End();
|
|
|
|
private:
|
|
// Return the name to use for register REG.
|
|
- string RegisterName(int i);
|
|
+ const UniqueString* RegisterName(int i);
|
|
|
|
// Record RULE for register REG at ADDRESS.
|
|
void Record(Module::Address address, int reg, const Module::Expr &rule);
|
|
|
|
// The module to which we should add entries.
|
|
Module *module_;
|
|
|
|
// Map from register numbers to register names.
|
|
- const vector<string> ®ister_names_;
|
|
+ const vector<const UniqueString*> ®ister_names_;
|
|
|
|
// The reporter to use to report problems.
|
|
Reporter *reporter_;
|
|
|
|
// The current entry we're constructing.
|
|
Module::StackFrameEntry *entry_;
|
|
|
|
// The section offset of the current frame description entry, for
|
|
// use in error messages.
|
|
size_t entry_offset_;
|
|
|
|
// The return address column for that entry.
|
|
unsigned return_address_;
|
|
-
|
|
- // The names of the return address and canonical frame address. Putting
|
|
- // these here instead of using string literals allows us to share their
|
|
- // texts in reference-counted std::string implementations (all the
|
|
- // popular ones). Many, many rules cite these strings.
|
|
- string cfa_name_, ra_name_;
|
|
-
|
|
- // A set of strings used by this CFI. Before storing a string in one of
|
|
- // our data structures, insert it into this set, and then use the string
|
|
- // from the set.
|
|
- //
|
|
- // Because std::string uses reference counting internally, simply using
|
|
- // strings from this set, even if passed by value, assigned, or held
|
|
- // directly in structures and containers (map<string, ...>, for example),
|
|
- // causes those strings to share a single instance of each distinct piece
|
|
- // of text.
|
|
- set<string> common_strings_;
|
|
};
|
|
|
|
} // namespace google_breakpad
|
|
|
|
#endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H
|
|
diff --git a/src/common/dwarf_cfi_to_module_unittest.cc b/src/common/dwarf_cfi_to_module_unittest.cc
|
|
--- a/src/common/dwarf_cfi_to_module_unittest.cc
|
|
+++ b/src/common/dwarf_cfi_to_module_unittest.cc
|
|
@@ -37,52 +37,59 @@
|
|
#include "breakpad_googletest_includes.h"
|
|
#include "common/dwarf_cfi_to_module.h"
|
|
#include "common/using_std_string.h"
|
|
|
|
using std::vector;
|
|
|
|
using google_breakpad::Module;
|
|
using google_breakpad::DwarfCFIToModule;
|
|
+using google_breakpad::ToUniqueString;
|
|
+using google_breakpad::UniqueString;
|
|
+using google_breakpad::ustr__ZDcfa;
|
|
+using google_breakpad::ustr__ZDra;
|
|
+using google_breakpad::ustr__empty;
|
|
using testing::ContainerEq;
|
|
using testing::Test;
|
|
using testing::_;
|
|
|
|
struct MockCFIReporter: public DwarfCFIToModule::Reporter {
|
|
MockCFIReporter(const string &file, const string §ion)
|
|
: Reporter(file, section) { }
|
|
MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg));
|
|
- MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string ®));
|
|
- MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string ®));
|
|
+ MOCK_METHOD2(UndefinedNotSupported, void(size_t offset,
|
|
+ const UniqueString* reg));
|
|
+ MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset,
|
|
+ const UniqueString* reg));
|
|
};
|
|
|
|
struct DwarfCFIToModuleFixture {
|
|
DwarfCFIToModuleFixture()
|
|
: module("module name", "module os", "module arch", "module id"),
|
|
reporter("reporter file", "reporter section"),
|
|
handler(&module, register_names, &reporter) {
|
|
- register_names.push_back("reg0");
|
|
- register_names.push_back("reg1");
|
|
- register_names.push_back("reg2");
|
|
- register_names.push_back("reg3");
|
|
- register_names.push_back("reg4");
|
|
- register_names.push_back("reg5");
|
|
- register_names.push_back("reg6");
|
|
- register_names.push_back("reg7");
|
|
- register_names.push_back("sp");
|
|
- register_names.push_back("pc");
|
|
- register_names.push_back("");
|
|
+ register_names.push_back(ToUniqueString("reg0"));
|
|
+ register_names.push_back(ToUniqueString("reg1"));
|
|
+ register_names.push_back(ToUniqueString("reg2"));
|
|
+ register_names.push_back(ToUniqueString("reg3"));
|
|
+ register_names.push_back(ToUniqueString("reg4"));
|
|
+ register_names.push_back(ToUniqueString("reg5"));
|
|
+ register_names.push_back(ToUniqueString("reg6"));
|
|
+ register_names.push_back(ToUniqueString("reg7"));
|
|
+ register_names.push_back(ToUniqueString("sp"));
|
|
+ register_names.push_back(ToUniqueString("pc"));
|
|
+ register_names.push_back(ustr__empty());
|
|
|
|
EXPECT_CALL(reporter, UnnamedRegister(_, _)).Times(0);
|
|
EXPECT_CALL(reporter, UndefinedNotSupported(_, _)).Times(0);
|
|
EXPECT_CALL(reporter, ExpressionsNotSupported(_, _)).Times(0);
|
|
}
|
|
|
|
Module module;
|
|
- vector<string> register_names;
|
|
+ vector<const UniqueString*> register_names;
|
|
MockCFIReporter reporter;
|
|
DwarfCFIToModule handler;
|
|
vector<Module::StackFrameEntry *> entries;
|
|
};
|
|
|
|
class Entry: public DwarfCFIToModuleFixture, public Test { };
|
|
|
|
TEST_F(Entry, Accept) {
|
|
@@ -127,183 +134,190 @@
|
|
}
|
|
uint64 entry_address, entry_size;
|
|
unsigned return_reg;
|
|
};
|
|
|
|
class Rule: public RuleFixture, public Test { };
|
|
|
|
TEST_F(Rule, UndefinedRule) {
|
|
- EXPECT_CALL(reporter, UndefinedNotSupported(_, "reg7"));
|
|
+ EXPECT_CALL(reporter, UndefinedNotSupported(_, ToUniqueString("reg7")));
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.UndefinedRule(entry_address, 7));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, RegisterWithEmptyName) {
|
|
EXPECT_CALL(reporter, UnnamedRegister(_, 10));
|
|
- EXPECT_CALL(reporter, UndefinedNotSupported(_, "unnamed_register10"));
|
|
+ EXPECT_CALL(reporter,
|
|
+ UndefinedNotSupported(_, ToUniqueString("unnamed_register10")));
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.UndefinedRule(entry_address, 10));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, SameValueRule) {
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.SameValueRule(entry_address, 6));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
Module::RuleMap expected_initial;
|
|
- expected_initial["reg6"] = Module::Expr("reg6", 0, false);
|
|
+ const UniqueString* reg6 = ToUniqueString("reg6");
|
|
+ expected_initial[reg6] = Module::Expr(reg6, 0, false);
|
|
EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, OffsetRule) {
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.OffsetRule(entry_address + 1, return_reg,
|
|
DwarfCFIToModule::kCFARegister,
|
|
16927065));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
Module::RuleChangeMap expected_changes;
|
|
- expected_changes[entry_address + 1][".ra"] =
|
|
- Module::Expr(".cfa", 16927065, true);
|
|
+ expected_changes[entry_address + 1][ustr__ZDra()] =
|
|
+ Module::Expr(ustr__ZDcfa(), 16927065, true);
|
|
EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
|
|
}
|
|
|
|
TEST_F(Rule, OffsetRuleNegative) {
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.OffsetRule(entry_address + 1,
|
|
DwarfCFIToModule::kCFARegister, 4, -34530721));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
Module::RuleChangeMap expected_changes;
|
|
- expected_changes[entry_address + 1][".cfa"] =
|
|
- Module::Expr("reg4", -34530721, true);
|
|
+ expected_changes[entry_address + 1][ustr__ZDcfa()] =
|
|
+ Module::Expr(ToUniqueString("reg4"), -34530721, true);
|
|
EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
|
|
}
|
|
|
|
TEST_F(Rule, ValOffsetRule) {
|
|
// Use an unnamed register number, to exercise that branch of RegisterName.
|
|
EXPECT_CALL(reporter, UnnamedRegister(_, 11));
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.ValOffsetRule(entry_address + 0x5ab7,
|
|
DwarfCFIToModule::kCFARegister,
|
|
11, 61812979));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
Module::RuleChangeMap expected_changes;
|
|
- expected_changes[entry_address + 0x5ab7][".cfa"] =
|
|
- Module::Expr("unnamed_register11", 61812979, false);
|
|
+ expected_changes[entry_address + 0x5ab7][ustr__ZDcfa()] =
|
|
+ Module::Expr(ToUniqueString("unnamed_register11"), 61812979, false);
|
|
EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
|
|
}
|
|
|
|
TEST_F(Rule, RegisterRule) {
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 3));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
Module::RuleMap expected_initial;
|
|
- expected_initial[".ra"] = Module::Expr("reg3", 0, false);
|
|
+ expected_initial[ustr__ZDra()] =
|
|
+ Module::Expr(ToUniqueString("reg3"), 0, false);
|
|
EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, ExpressionRule) {
|
|
- EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg2"));
|
|
+ EXPECT_CALL(reporter, ExpressionsNotSupported(_, ToUniqueString("reg2")));
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.ExpressionRule(entry_address + 0xf326, 2,
|
|
"it takes two to tango"));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, ValExpressionRule) {
|
|
- EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg0"));
|
|
+ EXPECT_CALL(reporter, ExpressionsNotSupported(_, ToUniqueString("reg0")));
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.ValExpressionRule(entry_address + 0x6367, 0,
|
|
"bit off more than he could chew"));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
EXPECT_EQ(0U, entries[0]->initial_rules.size());
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, DefaultReturnAddressRule) {
|
|
return_reg = 2;
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.RegisterRule(entry_address, 0, 1));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
Module::RuleMap expected_initial;
|
|
- expected_initial[".ra"] = Module::Expr("reg2", 0, false);
|
|
- expected_initial["reg0"] = Module::Expr("reg1", 0, false);
|
|
+ expected_initial[ustr__ZDra()] =
|
|
+ Module::Expr(ToUniqueString("reg2"), 0, false);
|
|
+ expected_initial[ToUniqueString("reg0")] =
|
|
+ Module::Expr(ToUniqueString("reg1"), 0, false);
|
|
EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, DefaultReturnAddressRuleOverride) {
|
|
return_reg = 2;
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 1));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
Module::RuleMap expected_initial;
|
|
- expected_initial[".ra"] = Module::Expr("reg1", 0, false);
|
|
+ expected_initial[ustr__ZDra()] =
|
|
+ Module::Expr(ToUniqueString("reg1"), 0, false);
|
|
EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
|
|
EXPECT_EQ(0U, entries[0]->rule_changes.size());
|
|
}
|
|
|
|
TEST_F(Rule, DefaultReturnAddressRuleLater) {
|
|
return_reg = 2;
|
|
StartEntry();
|
|
ASSERT_TRUE(handler.RegisterRule(entry_address + 1, return_reg, 1));
|
|
ASSERT_TRUE(handler.End());
|
|
CheckEntry();
|
|
Module::RuleMap expected_initial;
|
|
- expected_initial[".ra"] = Module::Expr("reg2", 0, false);
|
|
+ expected_initial[ustr__ZDra()] =
|
|
+ Module::Expr(ToUniqueString("reg2"), 0, false);
|
|
EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
|
|
Module::RuleChangeMap expected_changes;
|
|
- expected_changes[entry_address + 1][".ra"] =
|
|
- Module::Expr("reg1", 0, false);
|
|
+ expected_changes[entry_address + 1][ustr__ZDra()] =
|
|
+ Module::Expr(ToUniqueString("reg1"), 0, false);
|
|
EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
|
|
}
|
|
|
|
TEST(RegisterNames, I386) {
|
|
- vector<string> names = DwarfCFIToModule::RegisterNames::I386();
|
|
+ vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::I386();
|
|
|
|
- EXPECT_EQ("$eax", names[0]);
|
|
- EXPECT_EQ("$ecx", names[1]);
|
|
- EXPECT_EQ("$esp", names[4]);
|
|
- EXPECT_EQ("$eip", names[8]);
|
|
+ EXPECT_EQ(ToUniqueString("$eax"), names[0]);
|
|
+ EXPECT_EQ(ToUniqueString("$ecx"), names[1]);
|
|
+ EXPECT_EQ(ToUniqueString("$esp"), names[4]);
|
|
+ EXPECT_EQ(ToUniqueString("$eip"), names[8]);
|
|
}
|
|
|
|
TEST(RegisterNames, ARM) {
|
|
- vector<string> names = DwarfCFIToModule::RegisterNames::ARM();
|
|
+ vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::ARM();
|
|
|
|
- EXPECT_EQ("r0", names[0]);
|
|
- EXPECT_EQ("r10", names[10]);
|
|
- EXPECT_EQ("sp", names[13]);
|
|
- EXPECT_EQ("lr", names[14]);
|
|
- EXPECT_EQ("pc", names[15]);
|
|
+ EXPECT_EQ(ToUniqueString("r0"), names[0]);
|
|
+ EXPECT_EQ(ToUniqueString("r10"), names[10]);
|
|
+ EXPECT_EQ(ToUniqueString("sp"), names[13]);
|
|
+ EXPECT_EQ(ToUniqueString("lr"), names[14]);
|
|
+ EXPECT_EQ(ToUniqueString("pc"), names[15]);
|
|
}
|
|
|
|
TEST(RegisterNames, X86_64) {
|
|
- vector<string> names = DwarfCFIToModule::RegisterNames::X86_64();
|
|
+ vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::X86_64();
|
|
|
|
- EXPECT_EQ("$rax", names[0]);
|
|
- EXPECT_EQ("$rdx", names[1]);
|
|
- EXPECT_EQ("$rbp", names[6]);
|
|
- EXPECT_EQ("$rsp", names[7]);
|
|
- EXPECT_EQ("$rip", names[16]);
|
|
+ EXPECT_EQ(ToUniqueString("$rax"), names[0]);
|
|
+ EXPECT_EQ(ToUniqueString("$rdx"), names[1]);
|
|
+ EXPECT_EQ(ToUniqueString("$rbp"), names[6]);
|
|
+ EXPECT_EQ(ToUniqueString("$rsp"), names[7]);
|
|
+ EXPECT_EQ(ToUniqueString("$rip"), names[16]);
|
|
}
|
|
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
|
|
--- a/src/common/linux/dump_symbols.cc
|
|
+++ b/src/common/linux/dump_symbols.cc
|
|
@@ -81,16 +81,17 @@
|
|
using google_breakpad::ElfClass64;
|
|
using google_breakpad::FindElfSectionByName;
|
|
using google_breakpad::GetOffset;
|
|
using google_breakpad::IsValidElf;
|
|
using google_breakpad::Module;
|
|
#ifndef NO_STABS_SUPPORT
|
|
using google_breakpad::StabsToModule;
|
|
#endif
|
|
+using google_breakpad::UniqueString;
|
|
using google_breakpad::scoped_ptr;
|
|
|
|
//
|
|
// FDWrapper
|
|
//
|
|
// Wrapper class to make sure opened file is closed.
|
|
//
|
|
class FDWrapper {
|
|
@@ -278,17 +279,17 @@
|
|
|
|
// Fill REGISTER_NAMES with the register names appropriate to the
|
|
// machine architecture given in HEADER, indexed by the register
|
|
// numbers used in DWARF call frame information. Return true on
|
|
// success, or false if HEADER's machine architecture is not
|
|
// supported.
|
|
template<typename ElfClass>
|
|
bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
|
|
- std::vector<string>* register_names) {
|
|
+ std::vector<const UniqueString*>* register_names) {
|
|
switch (elf_header->e_machine) {
|
|
case EM_386:
|
|
*register_names = DwarfCFIToModule::RegisterNames::I386();
|
|
return true;
|
|
case EM_ARM:
|
|
*register_names = DwarfCFIToModule::RegisterNames::ARM();
|
|
return true;
|
|
case EM_X86_64:
|
|
@@ -306,17 +307,17 @@
|
|
const typename ElfClass::Shdr* section,
|
|
const bool eh_frame,
|
|
const typename ElfClass::Shdr* got_section,
|
|
const typename ElfClass::Shdr* text_section,
|
|
const bool big_endian,
|
|
Module* module) {
|
|
// Find the appropriate set of register names for this file's
|
|
// architecture.
|
|
- std::vector<string> register_names;
|
|
+ std::vector<const UniqueString*> register_names;
|
|
if (!DwarfCFIRegisterNames<ElfClass>(elf_header, ®ister_names)) {
|
|
fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';"
|
|
" cannot convert DWARF call frame information\n",
|
|
dwarf_filename.c_str(), elf_header->e_machine);
|
|
return false;
|
|
}
|
|
|
|
const dwarf2reader::Endianness endianness = big_endian ?
|
|
diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.mm
|
|
--- a/src/common/mac/dump_syms.mm
|
|
+++ b/src/common/mac/dump_syms.mm
|
|
@@ -313,17 +313,17 @@
|
|
}
|
|
|
|
bool DumpSymbols::ReadCFI(google_breakpad::Module *module,
|
|
const mach_o::Reader &macho_reader,
|
|
const mach_o::Section §ion,
|
|
bool eh_frame) const {
|
|
// Find the appropriate set of register names for this file's
|
|
// architecture.
|
|
- vector<string> register_names;
|
|
+ vector<const UniqueString*> register_names;
|
|
switch (macho_reader.cpu_type()) {
|
|
case CPU_TYPE_X86:
|
|
register_names = DwarfCFIToModule::RegisterNames::I386();
|
|
break;
|
|
case CPU_TYPE_X86_64:
|
|
register_names = DwarfCFIToModule::RegisterNames::X86_64();
|
|
break;
|
|
case CPU_TYPE_ARM:
|
|
diff --git a/src/common/module.cc b/src/common/module.cc
|
|
--- a/src/common/module.cc
|
|
+++ b/src/common/module.cc
|
|
@@ -33,16 +33,17 @@
|
|
|
|
#include "common/module.h"
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
+#include <algorithm>
|
|
#include <iostream>
|
|
#include <utility>
|
|
|
|
namespace google_breakpad {
|
|
|
|
using std::dec;
|
|
using std::endl;
|
|
using std::hex;
|
|
@@ -255,36 +256,50 @@
|
|
strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Module::Expr& expr) {
|
|
assert(!expr.invalid());
|
|
switch (expr.how_) {
|
|
case Module::kExprSimple:
|
|
- stream << expr.ident_ << " " << expr.offset_ << " +";
|
|
+ stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " +";
|
|
break;
|
|
case Module::kExprSimpleMem:
|
|
- stream << expr.ident_ << " " << expr.offset_ << " + ^";
|
|
+ stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " + ^";
|
|
break;
|
|
case Module::kExprPostfix:
|
|
stream << expr.postfix_; break;
|
|
case Module::kExprInvalid:
|
|
default:
|
|
break;
|
|
}
|
|
return stream;
|
|
}
|
|
|
|
bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) {
|
|
+ // Visit the register rules in alphabetical order. Because
|
|
+ // rule_map has the elements in some arbitrary order,
|
|
+ // get the names out into a vector, sort them, and visit in
|
|
+ // sorted order.
|
|
+ std::vector<const UniqueString*> rr_names;
|
|
for (RuleMap::const_iterator it = rule_map.begin();
|
|
it != rule_map.end(); ++it) {
|
|
- if (it != rule_map.begin())
|
|
- stream << ' ';
|
|
- stream << it->first << ": " << it->second;
|
|
+ rr_names.push_back(it->first);
|
|
+ }
|
|
+
|
|
+ std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString);
|
|
+
|
|
+ // Now visit the register rules in alphabetical order.
|
|
+ for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin();
|
|
+ name != rr_names.end();
|
|
+ ++name) {
|
|
+ if (name != rr_names.begin())
|
|
+ stream << " ";
|
|
+ stream << FromUniqueString(*name) << ": " << rule_map.find(*name)->second;
|
|
}
|
|
return stream.good();
|
|
}
|
|
|
|
bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
|
|
stream << "MODULE " << os_ << " " << architecture_ << " "
|
|
<< id_ << " " << name_ << endl;
|
|
if (!stream.good())
|
|
diff --git a/src/common/module.h b/src/common/module.h
|
|
--- a/src/common/module.h
|
|
+++ b/src/common/module.h
|
|
@@ -41,16 +41,17 @@
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "common/symbol_data.h"
|
|
#include "common/using_std_string.h"
|
|
+#include "common/unique_string.h"
|
|
#include "google_breakpad/common/breakpad_types.h"
|
|
|
|
namespace google_breakpad {
|
|
|
|
using std::set;
|
|
using std::vector;
|
|
using std::map;
|
|
|
|
@@ -131,69 +132,69 @@
|
|
enum ExprHow {
|
|
kExprInvalid = 1,
|
|
kExprPostfix,
|
|
kExprSimple,
|
|
kExprSimpleMem
|
|
};
|
|
struct Expr {
|
|
// Construct a simple-form expression
|
|
- Expr(string ident, long offset, bool deref) {
|
|
- if (ident.empty()) {
|
|
+ Expr(const UniqueString* ident, long offset, bool deref) {
|
|
+ if (ident == ustr__empty()) {
|
|
Expr();
|
|
} else {
|
|
postfix_ = "";
|
|
ident_ = ident;
|
|
offset_ = offset;
|
|
how_ = deref ? kExprSimpleMem : kExprSimple;
|
|
}
|
|
}
|
|
// Construct an expression from a postfix string
|
|
Expr(string postfix) {
|
|
if (postfix.empty()) {
|
|
Expr();
|
|
} else {
|
|
postfix_ = postfix;
|
|
- ident_ = "";
|
|
+ ident_ = NULL;
|
|
offset_ = 0;
|
|
how_ = kExprPostfix;
|
|
}
|
|
}
|
|
// Construct an invalid expression
|
|
Expr() {
|
|
postfix_ = "";
|
|
- ident_ = "";
|
|
+ ident_ = NULL;
|
|
offset_ = 0;
|
|
how_ = kExprInvalid;
|
|
}
|
|
bool invalid() const { return how_ == kExprInvalid; }
|
|
bool operator==(const Expr& other) const {
|
|
return how_ == other.how_ &&
|
|
ident_ == other.ident_ &&
|
|
offset_ == other.offset_ &&
|
|
postfix_ == other.postfix_;
|
|
}
|
|
|
|
// The identifier that gives the starting value for simple expressions.
|
|
- string ident_;
|
|
+ const UniqueString* ident_;
|
|
// The offset to add for simple expressions.
|
|
long offset_;
|
|
// The Postfix expression string to evaluate for non-simple expressions.
|
|
string postfix_;
|
|
// The operation expressed by this expression.
|
|
ExprHow how_;
|
|
|
|
friend std::ostream& operator<<(std::ostream& stream, const Expr& expr);
|
|
};
|
|
|
|
// A map from register names to expressions that recover
|
|
// their values. This can represent a complete set of rules to
|
|
// follow at some address, or a set of changes to be applied to an
|
|
// extant set of rules.
|
|
- typedef map<string, Expr> RuleMap;
|
|
+ typedef map<const UniqueString*, Expr> RuleMap;
|
|
|
|
// A map from addresses to RuleMaps, representing changes that take
|
|
// effect at given addresses.
|
|
typedef map<Address, RuleMap> RuleChangeMap;
|
|
|
|
// A range of 'STACK CFI' stack walking information. An instance of
|
|
// this structure corresponds to a 'STACK CFI INIT' record and the
|
|
// subsequent 'STACK CFI' records that fall within its range.
|
|
diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
|
|
--- a/src/common/module_unittest.cc
|
|
+++ b/src/common/module_unittest.cc
|
|
@@ -40,16 +40,18 @@
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "breakpad_googletest_includes.h"
|
|
#include "common/module.h"
|
|
#include "common/using_std_string.h"
|
|
|
|
using google_breakpad::Module;
|
|
+using google_breakpad::ToUniqueString;
|
|
+using google_breakpad::ustr__ZDcfa;
|
|
using std::stringstream;
|
|
using std::vector;
|
|
using testing::ContainerEq;
|
|
|
|
static Module::Function *generate_duplicate_function(const string &name) {
|
|
const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL;
|
|
const Module::Address DUP_SIZE = 0x200b26e605f99071LL;
|
|
const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
|
|
@@ -125,21 +127,27 @@
|
|
function->lines.push_back(line1);
|
|
|
|
m.AddFunction(function);
|
|
|
|
// Some stack information.
|
|
Module::StackFrameEntry *entry = new Module::StackFrameEntry();
|
|
entry->address = 0x30f9e5c83323973dULL;
|
|
entry->size = 0x49fc9ca7c7c13dc2ULL;
|
|
- entry->initial_rules[".cfa"] = Module::Expr("he was a handsome man");
|
|
- entry->initial_rules["and"] = Module::Expr("what i want to know is");
|
|
- entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
|
|
- Module::Expr("do you like your blueeyed boy");
|
|
- entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = Module::Expr("Death");
|
|
+ entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man");
|
|
+ entry->initial_rules[ToUniqueString("and")] =
|
|
+ Module::Expr("what i want to know is");
|
|
+ entry->initial_rules[ToUniqueString("stallion")] =
|
|
+ Module::Expr(ToUniqueString("and break"), 8, false);
|
|
+ entry->initial_rules[ToUniqueString("onetwothreefourfive")] =
|
|
+ Module::Expr(ToUniqueString("pigeonsjustlikethat"), 42, true);
|
|
+ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] =
|
|
+ Module::Expr("do you like your blueeyed boy");
|
|
+ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] =
|
|
+ Module::Expr("Death");
|
|
m.AddStackFrameEntry(entry);
|
|
|
|
// Set the load address. Doing this after adding all the data to
|
|
// the module must work fine.
|
|
m.SetLoadAddress(0x2ab698b0b6407073LL);
|
|
|
|
m.Write(s, ALL_SYMBOL_DATA);
|
|
string contents = s.str();
|
|
@@ -147,17 +155,19 @@
|
|
"FILE 0 filename-a.cc\n"
|
|
"FILE 1 filename-b.cc\n"
|
|
"FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
|
|
" A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
|
|
"b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n"
|
|
"9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n"
|
|
"STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2"
|
|
" .cfa: he was a handsome man"
|
|
- " and: what i want to know is\n"
|
|
+ " and: what i want to know is"
|
|
+ " onetwothreefourfive: pigeonsjustlikethat 42 + ^"
|
|
+ " stallion: and break 8 +\n"
|
|
"STACK CFI 6434d177ce326cb"
|
|
" Mister: Death"
|
|
" how: do you like your blueeyed boy\n",
|
|
contents.c_str());
|
|
}
|
|
|
|
TEST(Write, OmitUnusedFiles) {
|
|
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
|
|
@@ -229,21 +239,23 @@
|
|
function->lines.push_back(line1);
|
|
|
|
m.AddFunction(function);
|
|
|
|
// Some stack information.
|
|
Module::StackFrameEntry *entry = new Module::StackFrameEntry();
|
|
entry->address = 0x30f9e5c83323973dULL;
|
|
entry->size = 0x49fc9ca7c7c13dc2ULL;
|
|
- entry->initial_rules[".cfa"] = Module::Expr("he was a handsome man");
|
|
- entry->initial_rules["and"] = Module::Expr("what i want to know is");
|
|
- entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
|
|
- Module::Expr("do you like your blueeyed boy");
|
|
- entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = Module::Expr("Death");
|
|
+ entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man");
|
|
+ entry->initial_rules[ToUniqueString("and")] =
|
|
+ Module::Expr("what i want to know is");
|
|
+ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] =
|
|
+ Module::Expr("do you like your blueeyed boy");
|
|
+ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] =
|
|
+ Module::Expr("Death");
|
|
m.AddStackFrameEntry(entry);
|
|
|
|
// Set the load address. Doing this after adding all the data to
|
|
// the module must work fine.
|
|
m.SetLoadAddress(0x2ab698b0b6407073LL);
|
|
|
|
m.Write(s, NO_CFI);
|
|
string contents = s.str();
|
|
@@ -305,33 +317,36 @@
|
|
entry1->address = 0xddb5f41285aa7757ULL;
|
|
entry1->size = 0x1486493370dc5073ULL;
|
|
m.AddStackFrameEntry(entry1);
|
|
|
|
// Second STACK CFI entry, with initial rules but no deltas.
|
|
Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
|
|
entry2->address = 0x8064f3af5e067e38ULL;
|
|
entry2->size = 0x0de2a5ee55509407ULL;
|
|
- entry2->initial_rules[".cfa"] = Module::Expr("I think that I shall never see");
|
|
- entry2->initial_rules["stromboli"] = Module::Expr("a poem lovely as a tree");
|
|
- entry2->initial_rules["cannoli"] = Module::Expr("a tree whose hungry mouth is prest");
|
|
+ entry2->initial_rules[ustr__ZDcfa()] =
|
|
+ Module::Expr("I think that I shall never see");
|
|
+ entry2->initial_rules[ToUniqueString("stromboli")] =
|
|
+ Module::Expr("a poem lovely as a tree");
|
|
+ entry2->initial_rules[ToUniqueString("cannoli")] =
|
|
+ Module::Expr("a tree whose hungry mouth is prest");
|
|
m.AddStackFrameEntry(entry2);
|
|
|
|
// Third STACK CFI entry, with initial rules and deltas.
|
|
Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
|
|
entry3->address = 0x5e8d0db0a7075c6cULL;
|
|
entry3->size = 0x1c7edb12a7aea229ULL;
|
|
- entry3->initial_rules[".cfa"] = Module::Expr("Whose woods are these");
|
|
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
|
|
+ entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
|
|
+ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
|
|
Module::Expr("the village though");
|
|
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
|
|
+ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
|
|
Module::Expr("he will not see me stopping here");
|
|
- entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
|
|
+ entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
|
|
Module::Expr("his house is in");
|
|
- entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
|
|
+ entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
|
|
Module::Expr("I think I know");
|
|
m.AddStackFrameEntry(entry3);
|
|
|
|
// Check that Write writes STACK CFI records properly.
|
|
m.Write(s, ALL_SYMBOL_DATA);
|
|
string contents = s.str();
|
|
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
|
|
"STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
|
|
@@ -352,33 +367,39 @@
|
|
// Check that GetStackFrameEntries works.
|
|
vector<Module::StackFrameEntry *> entries;
|
|
m.GetStackFrameEntries(&entries);
|
|
ASSERT_EQ(3U, entries.size());
|
|
// Check first entry.
|
|
EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address);
|
|
EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size);
|
|
Module::RuleMap entry1_initial;
|
|
- entry1_initial[".cfa"] = Module::Expr("Whose woods are these");
|
|
+ entry1_initial[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
|
|
EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial));
|
|
Module::RuleChangeMap entry1_changes;
|
|
- entry1_changes[0x36682fad3763ffffULL][".cfa"] = Module::Expr("I think I know");
|
|
- entry1_changes[0x36682fad3763ffffULL]["stromboli"] = Module::Expr("his house is in");
|
|
- entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = Module::Expr("the village though");
|
|
- entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
|
|
- Module::Expr("he will not see me stopping here");
|
|
+ entry1_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
|
|
+ Module::Expr("I think I know");
|
|
+ entry1_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
|
|
+ Module::Expr("his house is in");
|
|
+ entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
|
|
+ Module::Expr("the village though");
|
|
+ entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
|
|
+ Module::Expr("he will not see me stopping here");
|
|
EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes));
|
|
// Check second entry.
|
|
EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
|
|
EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
|
|
ASSERT_EQ(3U, entries[1]->initial_rules.size());
|
|
Module::RuleMap entry2_initial;
|
|
- entry2_initial[".cfa"] = Module::Expr("I think that I shall never see");
|
|
- entry2_initial["stromboli"] = Module::Expr("a poem lovely as a tree");
|
|
- entry2_initial["cannoli"] = Module::Expr("a tree whose hungry mouth is prest");
|
|
+ entry2_initial[ustr__ZDcfa()] =
|
|
+ Module::Expr("I think that I shall never see");
|
|
+ entry2_initial[ToUniqueString("stromboli")] =
|
|
+ Module::Expr("a poem lovely as a tree");
|
|
+ entry2_initial[ToUniqueString("cannoli")] =
|
|
+ Module::Expr("a tree whose hungry mouth is prest");
|
|
EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
|
|
ASSERT_EQ(0U, entries[1]->rule_changes.size());
|
|
// Check third entry.
|
|
EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address);
|
|
EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size);
|
|
ASSERT_EQ(0U, entries[2]->initial_rules.size());
|
|
ASSERT_EQ(0U, entries[2]->rule_changes.size());
|
|
}
|
|
@@ -585,33 +606,36 @@
|
|
entry1->address = 0x2000;
|
|
entry1->size = 0x900;
|
|
m.AddStackFrameEntry(entry1);
|
|
|
|
// Second STACK CFI entry, with initial rules but no deltas.
|
|
Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
|
|
entry2->address = 0x3000;
|
|
entry2->size = 0x900;
|
|
- entry2->initial_rules[".cfa"] = Module::Expr("I think that I shall never see");
|
|
- entry2->initial_rules["stromboli"] = Module::Expr("a poem lovely as a tree");
|
|
- entry2->initial_rules["cannoli"] = Module::Expr("a tree whose hungry mouth is prest");
|
|
+ entry2->initial_rules[ustr__ZDcfa()] =
|
|
+ Module::Expr("I think that I shall never see");
|
|
+ entry2->initial_rules[ToUniqueString("stromboli")] =
|
|
+ Module::Expr("a poem lovely as a tree");
|
|
+ entry2->initial_rules[ToUniqueString("cannoli")] =
|
|
+ Module::Expr("a tree whose hungry mouth is prest");
|
|
m.AddStackFrameEntry(entry2);
|
|
|
|
// Third STACK CFI entry, with initial rules and deltas.
|
|
Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
|
|
entry3->address = 0x1000;
|
|
entry3->size = 0x900;
|
|
- entry3->initial_rules[".cfa"] = Module::Expr("Whose woods are these");
|
|
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
|
|
+ entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
|
|
+ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
|
|
Module::Expr("the village though");
|
|
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
|
|
+ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
|
|
Module::Expr("he will not see me stopping here");
|
|
- entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
|
|
+ entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
|
|
Module::Expr("his house is in");
|
|
- entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
|
|
+ entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
|
|
Module::Expr("I think I know");
|
|
m.AddStackFrameEntry(entry3);
|
|
|
|
Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000);
|
|
EXPECT_EQ(entry3, s);
|
|
s = m.FindStackFrameEntryByAddress(0x18FF);
|
|
EXPECT_EQ(entry3, s);
|
|
|
|
diff --git a/src/common/unique_string.cc b/src/common/unique_string.cc
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/src/common/unique_string.cc
|
|
@@ -0,0 +1,110 @@
|
|
+// Copyright (c) 2013 Google Inc.
|
|
+// All rights reserved.
|
|
+//
|
|
+// Redistribution and use in source and binary forms, with or without
|
|
+// modification, are permitted provided that the following conditions are
|
|
+// met:
|
|
+//
|
|
+// * Redistributions of source code must retain the above copyright
|
|
+// notice, this list of conditions and the following disclaimer.
|
|
+// * Redistributions in binary form must reproduce the above
|
|
+// copyright notice, this list of conditions and the following disclaimer
|
|
+// in the documentation and/or other materials provided with the
|
|
+// distribution.
|
|
+// * Neither the name of Google Inc. nor the names of its
|
|
+// contributors may be used to endorse or promote products derived from
|
|
+// this software without specific prior written permission.
|
|
+//
|
|
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
+
|
|
+#include <string>
|
|
+#include <map>
|
|
+
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include "common/unique_string.h"
|
|
+
|
|
+namespace google_breakpad {
|
|
+
|
|
+///////////////////////////////////////////////////////////////////
|
|
+// UniqueString
|
|
+//
|
|
+class UniqueString {
|
|
+ public:
|
|
+ UniqueString(string str) { str_ = strdup(str.c_str()); }
|
|
+ ~UniqueString() { free(reinterpret_cast<void*>(const_cast<char*>(str_))); }
|
|
+ const char* str_;
|
|
+};
|
|
+
|
|
+class UniqueStringUniverse {
|
|
+ public:
|
|
+ UniqueStringUniverse() {};
|
|
+ const UniqueString* FindOrCopy(string str) {
|
|
+ std::map<string, UniqueString*>::iterator it = map_.find(str);
|
|
+ if (it == map_.end()) {
|
|
+ UniqueString* ustr = new UniqueString(str);
|
|
+ map_[str] = ustr;
|
|
+ return ustr;
|
|
+ } else {
|
|
+ return it->second;
|
|
+ }
|
|
+ }
|
|
+ private:
|
|
+ std::map<string, UniqueString*> map_;
|
|
+};
|
|
+
|
|
+//
|
|
+///////////////////////////////////////////////////////////////////
|
|
+
|
|
+
|
|
+static UniqueStringUniverse* sUSU = NULL;
|
|
+
|
|
+
|
|
+// This isn't threadsafe.
|
|
+const UniqueString* ToUniqueString(string str) {
|
|
+ if (!sUSU) {
|
|
+ sUSU = new UniqueStringUniverse();
|
|
+ }
|
|
+ return sUSU->FindOrCopy(str);
|
|
+}
|
|
+
|
|
+// This isn't threadsafe.
|
|
+const UniqueString* ToUniqueString_n(const char* str, size_t n) {
|
|
+ if (!sUSU) {
|
|
+ sUSU = new UniqueStringUniverse();
|
|
+ }
|
|
+ string key(str, n);
|
|
+ return sUSU->FindOrCopy(key);
|
|
+}
|
|
+
|
|
+const char Index(const UniqueString* us, int ix)
|
|
+{
|
|
+ return us->str_[ix];
|
|
+}
|
|
+
|
|
+const char* const FromUniqueString(const UniqueString* ustr)
|
|
+{
|
|
+ return ustr->str_;
|
|
+}
|
|
+
|
|
+int StrcmpUniqueString(const UniqueString* us1, const UniqueString* us2) {
|
|
+ return strcmp(us1->str_, us2->str_);
|
|
+}
|
|
+
|
|
+bool LessThan_UniqueString(const UniqueString* us1, const UniqueString* us2) {
|
|
+ int r = StrcmpUniqueString(us1, us2);
|
|
+ return r < 0;
|
|
+}
|
|
+
|
|
+} // namespace google_breakpad
|
|
diff --git a/src/common/unique_string.h b/src/common/unique_string.h
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/src/common/unique_string.h
|
|
@@ -0,0 +1,239 @@
|
|
+// Copyright (c) 2013 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.
|
|
+
|
|
+#ifndef COMMON_UNIQUE_STRING_H_
|
|
+#define COMMON_UNIQUE_STRING_H_
|
|
+
|
|
+#include <string>
|
|
+#include "common/using_std_string.h"
|
|
+
|
|
+namespace google_breakpad {
|
|
+
|
|
+// Abstract type
|
|
+class UniqueString;
|
|
+
|
|
+// Unique-ify a string. |ToUniqueString| can never return NULL.
|
|
+const UniqueString* ToUniqueString(string);
|
|
+
|
|
+// ditto, starting instead from the first n characters of a C string
|
|
+const UniqueString* ToUniqueString_n(const char* str, size_t n);
|
|
+
|
|
+// Pull chars out of the string. No range checking.
|
|
+const char Index(const UniqueString*, int);
|
|
+
|
|
+// Get the contained C string (debugging only)
|
|
+const char* const FromUniqueString(const UniqueString*);
|
|
+
|
|
+// Do a strcmp-style comparison on the contained C string
|
|
+int StrcmpUniqueString(const UniqueString*, const UniqueString*);
|
|
+
|
|
+// Less-than comparison of two UniqueStrings, usable for std::sort.
|
|
+bool LessThan_UniqueString(const UniqueString*, const UniqueString*);
|
|
+
|
|
+// Some handy pre-uniqified strings. Z is an escape character:
|
|
+// ZS '$'
|
|
+// ZD '.'
|
|
+// Zeq '='
|
|
+// Zplus '+'
|
|
+// Zstar '*'
|
|
+// Zslash '/'
|
|
+// Zpercent '%'
|
|
+// Zat '@'
|
|
+// Zcaret '^'
|
|
+
|
|
+// Note that ustr__empty and (UniqueString*)NULL are considered
|
|
+// to be different.
|
|
+//
|
|
+// Unfortunately these have to be written as functions so as to
|
|
+// make them safe to use in static initialisers.
|
|
+
|
|
+// ""
|
|
+inline static const UniqueString* ustr__empty() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "$eip"
|
|
+inline static const UniqueString* ustr__ZSeip() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("$eip");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "$ebp"
|
|
+inline static const UniqueString* ustr__ZSebp() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("$ebp");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "$esp"
|
|
+inline static const UniqueString* ustr__ZSesp() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("$esp");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "$ebx"
|
|
+inline static const UniqueString* ustr__ZSebx() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("$ebx");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "$esi"
|
|
+inline static const UniqueString* ustr__ZSesi() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("$esi");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "$edi"
|
|
+inline static const UniqueString* ustr__ZSedi() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("$edi");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".cbCalleeParams"
|
|
+inline static const UniqueString* ustr__ZDcbCalleeParams() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".cbCalleeParams");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".cbSavedRegs"
|
|
+inline static const UniqueString* ustr__ZDcbSavedRegs() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".cbSavedRegs");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".cbLocals"
|
|
+inline static const UniqueString* ustr__ZDcbLocals() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".cbLocals");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".raSearchStart"
|
|
+inline static const UniqueString* ustr__ZDraSearchStart() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".raSearchStart");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".raSearch"
|
|
+inline static const UniqueString* ustr__ZDraSearch() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".raSearch");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".cbParams"
|
|
+inline static const UniqueString* ustr__ZDcbParams() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".cbParams");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "+"
|
|
+inline static const UniqueString* ustr__Zplus() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("+");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "-"
|
|
+inline static const UniqueString* ustr__Zminus() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("-");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "*"
|
|
+inline static const UniqueString* ustr__Zstar() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("*");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "/"
|
|
+inline static const UniqueString* ustr__Zslash() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("/");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "%"
|
|
+inline static const UniqueString* ustr__Zpercent() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("%");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "@"
|
|
+inline static const UniqueString* ustr__Zat() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("@");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "^"
|
|
+inline static const UniqueString* ustr__Zcaret() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("^");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// "="
|
|
+inline static const UniqueString* ustr__Zeq() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString("=");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".cfa"
|
|
+inline static const UniqueString* ustr__ZDcfa() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".cfa");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+// ".ra"
|
|
+inline static const UniqueString* ustr__ZDra() {
|
|
+ static const UniqueString* us = NULL;
|
|
+ if (!us) us = ToUniqueString(".ra");
|
|
+ return us;
|
|
+}
|
|
+
|
|
+} // namespace google_breakpad
|
|
+
|
|
+#endif // COMMON_UNIQUE_STRING_H_
|
|
diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
|
|
--- a/src/processor/basic_source_line_resolver_unittest.cc
|
|
+++ b/src/processor/basic_source_line_resolver_unittest.cc
|
|
@@ -43,21 +43,30 @@
|
|
#include "processor/windows_frame_info.h"
|
|
#include "processor/cfi_frame_info.h"
|
|
|
|
namespace {
|
|
|
|
using google_breakpad::BasicSourceLineResolver;
|
|
using google_breakpad::CFIFrameInfo;
|
|
using google_breakpad::CodeModule;
|
|
+using google_breakpad::FromUniqueString;
|
|
using google_breakpad::MemoryRegion;
|
|
using google_breakpad::StackFrame;
|
|
+using google_breakpad::ToUniqueString;
|
|
using google_breakpad::WindowsFrameInfo;
|
|
using google_breakpad::linked_ptr;
|
|
using google_breakpad::scoped_ptr;
|
|
+using google_breakpad::ustr__ZDcfa;
|
|
+using google_breakpad::ustr__ZDra;
|
|
+using google_breakpad::ustr__ZSebx;
|
|
+using google_breakpad::ustr__ZSebp;
|
|
+using google_breakpad::ustr__ZSedi;
|
|
+using google_breakpad::ustr__ZSesi;
|
|
+using google_breakpad::ustr__ZSesp;
|
|
|
|
class TestCodeModule : public CodeModule {
|
|
public:
|
|
TestCodeModule(string code_file) : code_file_(code_file) {}
|
|
virtual ~TestCodeModule() {}
|
|
|
|
virtual uint64_t base_address() const { return 0; }
|
|
virtual uint64_t size() const { return 0xb000; }
|
|
@@ -107,34 +116,34 @@
|
|
// association. (That is, ACTUAL's associations should be a subset of
|
|
// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
|
|
// ".cfa".
|
|
static bool VerifyRegisters(
|
|
const char *file, int line,
|
|
const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
|
|
const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
|
|
CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
|
|
- a = actual.find(".cfa");
|
|
+ a = actual.find(ustr__ZDcfa());
|
|
if (a == actual.end())
|
|
return false;
|
|
- a = actual.find(".ra");
|
|
+ a = actual.find(ustr__ZDra());
|
|
if (a == actual.end())
|
|
return false;
|
|
for (a = actual.begin(); a != actual.end(); a++) {
|
|
CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
|
|
expected.find(a->first);
|
|
if (e == expected.end()) {
|
|
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
|
|
- file, line, a->first.c_str(), a->second);
|
|
+ file, line, FromUniqueString(a->first), a->second);
|
|
return false;
|
|
}
|
|
if (e->second != a->second) {
|
|
fprintf(stderr,
|
|
"%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
|
|
- file, line, a->first.c_str(), a->second, e->second);
|
|
+ file, line, FromUniqueString(a->first), a->second, e->second);
|
|
return false;
|
|
}
|
|
// Don't complain if this doesn't recover all registers. Although
|
|
// the DWARF spec says that unmentioned registers are undefined,
|
|
// GCC uses omission to mean that they are unchanged.
|
|
}
|
|
return true;
|
|
}
|
|
@@ -254,81 +263,81 @@
|
|
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
|
|
MockMemoryRegion memory;
|
|
|
|
// Regardless of which instruction evaluation takes place at, it
|
|
// should produce the same values for the caller's registers.
|
|
- expected_caller_registers[".cfa"] = 0x1001c;
|
|
- expected_caller_registers[".ra"] = 0xf6438648;
|
|
- expected_caller_registers["$ebp"] = 0x10038;
|
|
- expected_caller_registers["$ebx"] = 0x98ecadc3;
|
|
- expected_caller_registers["$esi"] = 0x878f7524;
|
|
- expected_caller_registers["$edi"] = 0x6312f9a5;
|
|
+ expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
|
|
+ expected_caller_registers[ustr__ZDra()] = 0xf6438648;
|
|
+ expected_caller_registers[ustr__ZSebp()] = 0x10038;
|
|
+ expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
+ expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
|
|
+ expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
|
|
|
|
frame.instruction = 0x3d40;
|
|
frame.module = &module1;
|
|
current_registers.clear();
|
|
- current_registers["$esp"] = 0x10018;
|
|
- current_registers["$ebp"] = 0x10038;
|
|
- current_registers["$ebx"] = 0x98ecadc3;
|
|
- current_registers["$esi"] = 0x878f7524;
|
|
- current_registers["$edi"] = 0x6312f9a5;
|
|
+ current_registers[ustr__ZSesp()] = 0x10018;
|
|
+ current_registers[ustr__ZSebp()] = 0x10038;
|
|
+ current_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
+ current_registers[ustr__ZSesi()] = 0x878f7524;
|
|
+ current_registers[ustr__ZSedi()] = 0x6312f9a5;
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers));
|
|
|
|
frame.instruction = 0x3d41;
|
|
- current_registers["$esp"] = 0x10014;
|
|
+ current_registers[ustr__ZSesp()] = 0x10014;
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers));
|
|
|
|
frame.instruction = 0x3d43;
|
|
- current_registers["$ebp"] = 0x10014;
|
|
+ current_registers[ustr__ZSebp()] = 0x10014;
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
frame.instruction = 0x3d54;
|
|
- current_registers["$ebx"] = 0x6864f054U;
|
|
+ current_registers[ustr__ZSebx()] = 0x6864f054U;
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
frame.instruction = 0x3d5a;
|
|
- current_registers["$esi"] = 0x6285f79aU;
|
|
+ current_registers[ustr__ZSesi()] = 0x6285f79aU;
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
frame.instruction = 0x3d84;
|
|
- current_registers["$edi"] = 0x64061449U;
|
|
+ current_registers[ustr__ZSedi()] = 0x64061449U;
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
|
|
--- a/src/processor/cfi_frame_info.cc
|
|
+++ b/src/processor/cfi_frame_info.cc
|
|
@@ -31,16 +31,17 @@
|
|
|
|
// cfi_frame_info.cc: Implementation of CFIFrameInfo class.
|
|
// See cfi_frame_info.h for details.
|
|
|
|
#include "processor/cfi_frame_info.h"
|
|
|
|
#include <string.h>
|
|
|
|
+#include <algorithm>
|
|
#include <sstream>
|
|
|
|
#include "common/scoped_ptr.h"
|
|
#include "processor/postfix_evaluator-inl.h"
|
|
|
|
namespace google_breakpad {
|
|
|
|
#ifdef _WIN32
|
|
@@ -65,33 +66,33 @@
|
|
V cfa;
|
|
working = registers;
|
|
if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
|
|
return false;
|
|
|
|
// Then, compute the return address.
|
|
V ra;
|
|
working = registers;
|
|
- working[".cfa"] = cfa;
|
|
+ working[ustr__ZDcfa()] = cfa;
|
|
if (!evaluator.EvaluateForValue(ra_rule_, &ra))
|
|
return false;
|
|
|
|
// Now, compute values for all the registers register_rules_ mentions.
|
|
for (RuleMap::const_iterator it = register_rules_.begin();
|
|
it != register_rules_.end(); it++) {
|
|
V value;
|
|
working = registers;
|
|
- working[".cfa"] = cfa;
|
|
+ working[ustr__ZDcfa()] = cfa;
|
|
if (!evaluator.EvaluateForValue(it->second, &value))
|
|
return false;
|
|
(*caller_registers)[it->first] = value;
|
|
}
|
|
|
|
- (*caller_registers)[".ra"] = ra;
|
|
- (*caller_registers)[".cfa"] = cfa;
|
|
+ (*caller_registers)[ustr__ZDra()] = ra;
|
|
+ (*caller_registers)[ustr__ZDcfa()] = cfa;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Explicit instantiations for 32-bit and 64-bit architectures.
|
|
template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
|
|
const RegisterValueMap<uint32_t> ®isters,
|
|
const MemoryRegion &memory,
|
|
@@ -107,81 +108,98 @@
|
|
if (!cfa_rule_.invalid()) {
|
|
stream << ".cfa: " << cfa_rule_;
|
|
}
|
|
if (!ra_rule_.invalid()) {
|
|
if (static_cast<std::streamoff>(stream.tellp()) != 0)
|
|
stream << " ";
|
|
stream << ".ra: " << ra_rule_;
|
|
}
|
|
+
|
|
+ // Visit the register rules in alphabetical order. Because
|
|
+ // register_rules_ has the elements in some arbitrary order,
|
|
+ // get the names out into a vector, sort them, and visit in
|
|
+ // sorted order.
|
|
+ std::vector<const UniqueString*> rr_names;
|
|
for (RuleMap::const_iterator iter = register_rules_.begin();
|
|
iter != register_rules_.end();
|
|
++iter) {
|
|
+ rr_names.push_back(iter->first);
|
|
+ }
|
|
+
|
|
+ std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString);
|
|
+
|
|
+ // Now visit the register rules in alphabetical order.
|
|
+ for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin();
|
|
+ name != rr_names.end();
|
|
+ ++name) {
|
|
+ const UniqueString* nm = *name;
|
|
+ Module::Expr rule = register_rules_.find(nm)->second;
|
|
if (static_cast<std::streamoff>(stream.tellp()) != 0)
|
|
stream << " ";
|
|
- stream << iter->first << ": " << iter->second;
|
|
+ stream << FromUniqueString(nm) << ": " << rule;
|
|
}
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
bool CFIRuleParser::Parse(const string &rule_set) {
|
|
size_t rule_set_len = rule_set.size();
|
|
scoped_array<char> working_copy(new char[rule_set_len + 1]);
|
|
memcpy(working_copy.get(), rule_set.data(), rule_set_len);
|
|
working_copy[rule_set_len] = '\0';
|
|
|
|
- name_.clear();
|
|
+ name_ = ustr__empty();
|
|
expression_.clear();
|
|
|
|
char *cursor;
|
|
static const char token_breaks[] = " \t\r\n";
|
|
char *token = strtok_r(working_copy.get(), token_breaks, &cursor);
|
|
|
|
for (;;) {
|
|
// End of rule set?
|
|
if (!token) return Report();
|
|
|
|
// Register/pseudoregister name?
|
|
size_t token_len = strlen(token);
|
|
if (token_len >= 1 && token[token_len - 1] == ':') {
|
|
// Names can't be empty.
|
|
if (token_len < 2) return false;
|
|
// If there is any pending content, report it.
|
|
- if (!name_.empty() || !expression_.empty()) {
|
|
+ if (name_ != ustr__empty() || !expression_.empty()) {
|
|
if (!Report()) return false;
|
|
}
|
|
- name_.assign(token, token_len - 1);
|
|
+ name_ = ToUniqueString_n(token, token_len - 1);
|
|
expression_.clear();
|
|
} else {
|
|
// Another expression component.
|
|
assert(token_len > 0); // strtok_r guarantees this, I think.
|
|
if (!expression_.empty())
|
|
expression_ += ' ';
|
|
expression_ += token;
|
|
}
|
|
token = strtok_r(NULL, token_breaks, &cursor);
|
|
}
|
|
}
|
|
|
|
bool CFIRuleParser::Report() {
|
|
- if (name_.empty() || expression_.empty()) return false;
|
|
- if (name_ == ".cfa") handler_->CFARule(expression_);
|
|
- else if (name_ == ".ra") handler_->RARule(expression_);
|
|
+ if (name_ == ustr__empty() || expression_.empty()) return false;
|
|
+ if (name_ == ustr__ZDcfa()) handler_->CFARule(expression_);
|
|
+ else if (name_ == ustr__ZDra()) handler_->RARule(expression_);
|
|
else handler_->RegisterRule(name_, expression_);
|
|
return true;
|
|
}
|
|
|
|
void CFIFrameInfoParseHandler::CFARule(const string &expression) {
|
|
// 'expression' is a postfix expression string.
|
|
frame_info_->SetCFARule(Module::Expr(expression));
|
|
}
|
|
|
|
void CFIFrameInfoParseHandler::RARule(const string &expression) {
|
|
frame_info_->SetRARule(Module::Expr(expression));
|
|
}
|
|
|
|
-void CFIFrameInfoParseHandler::RegisterRule(const string &name,
|
|
+void CFIFrameInfoParseHandler::RegisterRule(const UniqueString* name,
|
|
const string &expression) {
|
|
frame_info_->SetRegisterRule(name, Module::Expr(expression));
|
|
}
|
|
|
|
} // namespace google_breakpad
|
|
diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
|
|
--- a/src/processor/cfi_frame_info.h
|
|
+++ b/src/processor/cfi_frame_info.h
|
|
@@ -37,16 +37,17 @@
|
|
|
|
#ifndef PROCESSOR_CFI_FRAME_INFO_H_
|
|
#define PROCESSOR_CFI_FRAME_INFO_H_
|
|
|
|
#include <map>
|
|
#include <string>
|
|
|
|
#include "common/using_std_string.h"
|
|
+#include "common/unique_string.h"
|
|
#include "google_breakpad/common/breakpad_types.h"
|
|
#include "common/module.h"
|
|
|
|
namespace google_breakpad {
|
|
|
|
using std::map;
|
|
|
|
class MemoryRegion;
|
|
@@ -63,24 +64,24 @@
|
|
// changes given by the 'STACK CFI' records up to our instruction's
|
|
// address. Then, use the FindCallerRegs member function to apply the
|
|
// rules to the callee frame's register values, yielding the caller
|
|
// frame's register values.
|
|
class CFIFrameInfo {
|
|
public:
|
|
// A map from register names onto values.
|
|
template<typename ValueType> class RegisterValueMap:
|
|
- public map<string, ValueType> { };
|
|
+ public map<const UniqueString*, ValueType> { };
|
|
|
|
// Set the expression for computing a call frame address, return
|
|
// address, or register's value. At least the CFA rule and the RA
|
|
// rule must be set before calling FindCallerRegs.
|
|
void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; }
|
|
void SetRARule(const Module::Expr& rule) { ra_rule_ = rule; }
|
|
- void SetRegisterRule(const string& register_name,
|
|
+ void SetRegisterRule(const UniqueString* register_name,
|
|
const Module::Expr& rule) {
|
|
register_rules_[register_name] = rule;
|
|
}
|
|
|
|
// Compute the values of the calling frame's registers, according to
|
|
// this rule set. Use ValueType in expression evaluation; this
|
|
// should be uint32_t on machines with 32-bit addresses, or
|
|
// uint64_t on machines with 64-bit addresses.
|
|
@@ -104,17 +105,17 @@
|
|
|
|
// Serialize the rules in this object into a string in the format
|
|
// of STACK CFI records.
|
|
string Serialize() const;
|
|
|
|
private:
|
|
|
|
// A map from register names onto evaluation rules.
|
|
- typedef map<string, Module::Expr> RuleMap;
|
|
+ typedef map<const UniqueString*, Module::Expr> RuleMap;
|
|
|
|
// An expression for computing the current frame's CFA (call
|
|
// frame address). The CFA is a reference address for the frame that
|
|
// remains unchanged throughout the frame's lifetime. You should
|
|
// evaluate this expression with a dictionary initially populated
|
|
// with the values of the current frame's known registers.
|
|
Module::Expr cfa_rule_;
|
|
|
|
@@ -145,17 +146,18 @@
|
|
Handler() { }
|
|
virtual ~Handler() { }
|
|
|
|
// The input specifies EXPRESSION as the CFA/RA computation rule.
|
|
virtual void CFARule(const string &expression) = 0;
|
|
virtual void RARule(const string &expression) = 0;
|
|
|
|
// The input specifies EXPRESSION as the recovery rule for register NAME.
|
|
- virtual void RegisterRule(const string &name, const string &expression) = 0;
|
|
+ virtual void RegisterRule(const UniqueString* name,
|
|
+ const string &expression) = 0;
|
|
};
|
|
|
|
// Construct a parser which feeds its results to HANDLER.
|
|
CFIRuleParser(Handler *handler) : handler_(handler) { }
|
|
|
|
// Parse RULE_SET as a set of CFA computation and RA/register
|
|
// recovery rules, as appearing in STACK CFI records. Report the
|
|
// results of parsing by making the appropriate calls to handler_.
|
|
@@ -165,30 +167,31 @@
|
|
private:
|
|
// Report any accumulated rule to handler_
|
|
bool Report();
|
|
|
|
// The handler to which the parser reports its findings.
|
|
Handler *handler_;
|
|
|
|
// Working data.
|
|
- string name_, expression_;
|
|
+ const UniqueString* name_;
|
|
+ string expression_;
|
|
};
|
|
|
|
// A handler for rule set parsing that populates a CFIFrameInfo with
|
|
// the results.
|
|
class CFIFrameInfoParseHandler: public CFIRuleParser::Handler {
|
|
public:
|
|
// Populate FRAME_INFO with the results of parsing.
|
|
CFIFrameInfoParseHandler(CFIFrameInfo *frame_info)
|
|
: frame_info_(frame_info) { }
|
|
|
|
void CFARule(const string &expression);
|
|
void RARule(const string &expression);
|
|
- void RegisterRule(const string &name, const string &expression);
|
|
+ void RegisterRule(const UniqueString* name, const string &expression);
|
|
|
|
private:
|
|
CFIFrameInfo *frame_info_;
|
|
};
|
|
|
|
// A utility class template for simple 'STACK CFI'-driven stack walkers.
|
|
// Given a CFIFrameInfo instance, a table describing the architecture's
|
|
// register set, and a context holding the last frame's registers, an
|
|
@@ -205,24 +208,24 @@
|
|
// uint32_t or uint64_t. RawContextType should be the raw context
|
|
// structure type for this architecture.
|
|
template <typename RegisterType, class RawContextType>
|
|
class SimpleCFIWalker {
|
|
public:
|
|
// A structure describing one architecture register.
|
|
struct RegisterSet {
|
|
// The register name, as it appears in STACK CFI rules.
|
|
- const char *name;
|
|
+ const UniqueString* name;
|
|
|
|
// An alternate name that the register's value might be found
|
|
// under in a register value dictionary, or NULL. When generating
|
|
// names, prefer NAME to this value. It's common to list ".cfa" as
|
|
// an alternative name for the stack pointer, and ".ra" as an
|
|
// alternative name for the instruction pointer.
|
|
- const char *alternate_name;
|
|
+ const UniqueString* alternate_name;
|
|
|
|
// True if the callee is expected to preserve the value of this
|
|
// register. If this flag is true for some register R, and the STACK
|
|
// CFI records provide no rule to recover R, then SimpleCFIWalker
|
|
// assumes that the callee has not changed R's value, and the caller's
|
|
// value for R is that currently in the callee's context.
|
|
bool callee_saves;
|
|
|
|
diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
|
|
--- a/src/processor/cfi_frame_info_unittest.cc
|
|
+++ b/src/processor/cfi_frame_info_unittest.cc
|
|
@@ -38,19 +38,24 @@
|
|
#include "common/module.h"
|
|
#include "common/using_std_string.h"
|
|
#include "processor/cfi_frame_info.h"
|
|
#include "google_breakpad/processor/memory_region.h"
|
|
|
|
using google_breakpad::CFIFrameInfo;
|
|
using google_breakpad::CFIFrameInfoParseHandler;
|
|
using google_breakpad::CFIRuleParser;
|
|
+using google_breakpad::FromUniqueString;
|
|
using google_breakpad::MemoryRegion;
|
|
using google_breakpad::Module;
|
|
using google_breakpad::SimpleCFIWalker;
|
|
+using google_breakpad::ToUniqueString;
|
|
+using google_breakpad::UniqueString;
|
|
+using google_breakpad::ustr__ZDcfa;
|
|
+using google_breakpad::ustr__ZDra;
|
|
using testing::_;
|
|
using testing::A;
|
|
using testing::AtMost;
|
|
using testing::DoAll;
|
|
using testing::Return;
|
|
using testing::SetArgumentPointee;
|
|
using testing::Test;
|
|
|
|
@@ -107,41 +112,47 @@
|
|
TEST_F(Simple, SetCFAAndRARule) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("330903416631436410"));
|
|
cfi.SetRARule(Module::Expr("5870666104170902211"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(2U, caller_registers.size());
|
|
- ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]);
|
|
- ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
|
|
+ ASSERT_EQ(330903416631436410ULL, caller_registers[ustr__ZDcfa()]);
|
|
+ ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
|
|
|
|
ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
|
|
cfi.Serialize());
|
|
}
|
|
|
|
TEST_F(Simple, SetManyRules) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -"));
|
|
cfi.SetRARule(Module::Expr(".cfa 99804755 +"));
|
|
- cfi.SetRegisterRule("register1", Module::Expr(".cfa 54370437 *"));
|
|
- cfi.SetRegisterRule("vodkathumbscrewingly", Module::Expr("24076308 .cfa +"));
|
|
- cfi.SetRegisterRule("pubvexingfjordschmaltzy", Module::Expr(".cfa 29801007 -"));
|
|
- cfi.SetRegisterRule("uncopyrightables", Module::Expr("92642917 .cfa /"));
|
|
+
|
|
+ const UniqueString* reg1 = ToUniqueString("register1");
|
|
+ const UniqueString* reg2 = ToUniqueString("vodkathumbscrewingly");
|
|
+ const UniqueString* reg3 = ToUniqueString("pubvexingfjordschmaltzy");
|
|
+ const UniqueString* reg4 = ToUniqueString("uncopyrightables");
|
|
+
|
|
+ cfi.SetRegisterRule(reg1, Module::Expr(".cfa 54370437 *"));
|
|
+ cfi.SetRegisterRule(reg2, Module::Expr("24076308 .cfa +"));
|
|
+ cfi.SetRegisterRule(reg3, Module::Expr(".cfa 29801007 -"));
|
|
+ cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(6U, caller_registers.size());
|
|
- ASSERT_EQ(7664691U, caller_registers[".cfa"]);
|
|
- ASSERT_EQ(107469446U, caller_registers[".ra"]);
|
|
- ASSERT_EQ(416732599139967ULL, caller_registers["register1"]);
|
|
- ASSERT_EQ(31740999U, caller_registers["vodkathumbscrewingly"]);
|
|
- ASSERT_EQ(-22136316ULL, caller_registers["pubvexingfjordschmaltzy"]);
|
|
- ASSERT_EQ(12U, caller_registers["uncopyrightables"]);
|
|
+ ASSERT_EQ(7664691U, caller_registers[ustr__ZDcfa()]);
|
|
+ ASSERT_EQ(107469446U, caller_registers[ustr__ZDra()]);
|
|
+ ASSERT_EQ(416732599139967ULL, caller_registers[reg1]);
|
|
+ ASSERT_EQ(31740999U, caller_registers[reg2]);
|
|
+ ASSERT_EQ(-22136316ULL, caller_registers[reg3]);
|
|
+ ASSERT_EQ(12U, caller_registers[reg4]);
|
|
ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
|
|
".ra: .cfa 99804755 + "
|
|
"pubvexingfjordschmaltzy: .cfa 29801007 - "
|
|
"register1: .cfa 54370437 * "
|
|
"uncopyrightables: 92642917 .cfa / "
|
|
"vodkathumbscrewingly: 24076308 .cfa +",
|
|
cfi.Serialize());
|
|
}
|
|
@@ -150,18 +161,18 @@
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("330903416631436410"));
|
|
cfi.SetRARule(Module::Expr("5870666104170902211"));
|
|
cfi.SetCFARule(Module::Expr("2828089117179001"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(2U, caller_registers.size());
|
|
- ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]);
|
|
- ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
|
|
+ ASSERT_EQ(2828089117179001ULL, caller_registers[ustr__ZDcfa()]);
|
|
+ ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
|
|
ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
|
|
cfi.Serialize());
|
|
}
|
|
|
|
class Scope: public CFIFixture, public Test { };
|
|
|
|
// There should be no value for .cfa in scope when evaluating the CFA rule.
|
|
TEST_F(Scope, CFALacksCFA) {
|
|
@@ -183,37 +194,39 @@
|
|
&caller_registers));
|
|
}
|
|
|
|
// The current frame's registers should be in scope when evaluating
|
|
// the CFA rule.
|
|
TEST_F(Scope, CFASeesCurrentRegs) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
- registers[".baraminology"] = 0x06a7bc63e4f13893ULL;
|
|
- registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL;
|
|
+ const UniqueString* reg1 = ToUniqueString(".baraminology");
|
|
+ const UniqueString* reg2 = ToUniqueString(".ornithorhynchus");
|
|
+ registers[reg1] = 0x06a7bc63e4f13893ULL;
|
|
+ registers[reg2] = 0x5e0bf850bafce9d2ULL;
|
|
cfi.SetCFARule(Module::Expr(".baraminology .ornithorhynchus +"));
|
|
cfi.SetRARule(Module::Expr("0"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(2U, caller_registers.size());
|
|
ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
|
|
- caller_registers[".cfa"]);
|
|
+ caller_registers[ustr__ZDcfa()]);
|
|
}
|
|
|
|
// .cfa should be in scope in the return address expression.
|
|
TEST_F(Scope, RASeesCFA) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("48364076"));
|
|
cfi.SetRARule(Module::Expr(".cfa"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(2U, caller_registers.size());
|
|
- ASSERT_EQ(48364076U, caller_registers[".ra"]);
|
|
+ ASSERT_EQ(48364076U, caller_registers[ustr__ZDra()]);
|
|
}
|
|
|
|
// There should be no value for .ra in scope when evaluating the CFA rule.
|
|
TEST_F(Scope, RALacksRA) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("0"));
|
|
cfi.SetRARule(Module::Expr(".ra"));
|
|
@@ -221,64 +234,69 @@
|
|
&caller_registers));
|
|
}
|
|
|
|
// The current frame's registers should be in scope in the return
|
|
// address expression.
|
|
TEST_F(Scope, RASeesCurrentRegs) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
- registers["noachian"] = 0x54dc4a5d8e5eb503ULL;
|
|
cfi.SetCFARule(Module::Expr("10359370"));
|
|
- cfi.SetRARule(Module::Expr("noachian"));
|
|
+ const UniqueString* reg1 = ToUniqueString("noachian");
|
|
+ registers[reg1] = 0x54dc4a5d8e5eb503ULL;
|
|
+ cfi.SetRARule(Module::Expr(reg1, 0, false));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(2U, caller_registers.size());
|
|
- ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]);
|
|
+ ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[ustr__ZDra()]);
|
|
}
|
|
|
|
// .cfa should be in scope for register rules.
|
|
TEST_F(Scope, RegistersSeeCFA) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("6515179"));
|
|
cfi.SetRARule(Module::Expr(".cfa"));
|
|
- cfi.SetRegisterRule("rogerian", Module::Expr(".cfa"));
|
|
+ const UniqueString* reg1 = ToUniqueString("rogerian");
|
|
+ cfi.SetRegisterRule(reg1, Module::Expr(".cfa"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(3U, caller_registers.size());
|
|
- ASSERT_EQ(6515179U, caller_registers["rogerian"]);
|
|
+ ASSERT_EQ(6515179U, caller_registers[reg1]);
|
|
}
|
|
|
|
// The return address should not be in scope for register rules.
|
|
TEST_F(Scope, RegsLackRA) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("42740329"));
|
|
cfi.SetRARule(Module::Expr("27045204"));
|
|
- cfi.SetRegisterRule("$r1", Module::Expr(".ra"));
|
|
+ const UniqueString* reg1 = ToUniqueString("$r1");
|
|
+ cfi.SetRegisterRule(reg1, Module::Expr(".ra"));
|
|
ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
}
|
|
|
|
// Register rules can see the current frame's register values.
|
|
TEST_F(Scope, RegsSeeRegs) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
- registers["$r1"] = 0x6ed3582c4bedb9adULL;
|
|
- registers["$r2"] = 0xd27d9e742b8df6d0ULL;
|
|
+ const UniqueString* reg1 = ToUniqueString("$r1");
|
|
+ const UniqueString* reg2 = ToUniqueString("$r2");
|
|
+ registers[reg1] = 0x6ed3582c4bedb9adULL;
|
|
+ registers[reg2] = 0xd27d9e742b8df6d0ULL;
|
|
cfi.SetCFARule(Module::Expr("88239303"));
|
|
cfi.SetRARule(Module::Expr("30503835"));
|
|
- cfi.SetRegisterRule("$r1", Module::Expr("$r1 42175211 = $r2"));
|
|
- cfi.SetRegisterRule("$r2", Module::Expr("$r2 21357221 = $r1"));
|
|
+ cfi.SetRegisterRule(reg1, Module::Expr("$r1 42175211 = $r2"));
|
|
+ cfi.SetRegisterRule(reg2, Module::Expr("$r2 21357221 = $r1"));
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
ASSERT_EQ(4U, caller_registers.size());
|
|
- ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]);
|
|
- ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]);
|
|
+ ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers[reg1]);
|
|
+ ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers[reg2]);
|
|
}
|
|
|
|
// Each rule's temporaries are separate.
|
|
TEST_F(Scope, SeparateTempsRA) {
|
|
ExpectNoMemoryReferences();
|
|
|
|
cfi.SetCFARule(Module::Expr("$temp1 76569129 = $temp1"));
|
|
cfi.SetRARule(Module::Expr("0"));
|
|
@@ -290,17 +308,17 @@
|
|
ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
}
|
|
|
|
class MockCFIRuleParserHandler: public CFIRuleParser::Handler {
|
|
public:
|
|
MOCK_METHOD1(CFARule, void(const string &));
|
|
MOCK_METHOD1(RARule, void(const string &));
|
|
- MOCK_METHOD2(RegisterRule, void(const string &, const string &));
|
|
+ MOCK_METHOD2(RegisterRule, void(const UniqueString*, const string &));
|
|
};
|
|
|
|
// A fixture class for testing CFIRuleParser.
|
|
class CFIParserFixture {
|
|
public:
|
|
CFIParserFixture() : parser(&mock_handler) {
|
|
// Expect no parsing results to be reported to mock_handler. Individual
|
|
// tests can override this.
|
|
@@ -361,100 +379,100 @@
|
|
}
|
|
|
|
TEST_F(Parser, RA) {
|
|
EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return());
|
|
EXPECT_TRUE(parser.Parse(".ra: notoriety"));
|
|
}
|
|
|
|
TEST_F(Parser, Reg) {
|
|
- EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("nemo"), "mellifluous"))
|
|
.WillOnce(Return());
|
|
EXPECT_TRUE(parser.Parse("nemo: mellifluous"));
|
|
}
|
|
|
|
TEST_F(Parser, CFARARegs) {
|
|
EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return());
|
|
EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return());
|
|
- EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("galba"), "praetorian"))
|
|
.WillOnce(Return());
|
|
- EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("otho"), "vitellius"))
|
|
.WillOnce(Return());
|
|
EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression "
|
|
"galba: praetorian otho: vitellius"));
|
|
}
|
|
|
|
TEST_F(Parser, Whitespace) {
|
|
- EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "r1 expression"))
|
|
.WillOnce(Return());
|
|
- EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r2"), "r2 expression"))
|
|
.WillOnce(Return());
|
|
EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n "
|
|
"expression \n"));
|
|
}
|
|
|
|
TEST_F(Parser, WhitespaceLoneColon) {
|
|
EXPECT_FALSE(parser.Parse(" \n:\t "));
|
|
}
|
|
|
|
TEST_F(Parser, EmptyName) {
|
|
- EXPECT_CALL(mock_handler, RegisterRule("reg", _))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("reg"), _))
|
|
.Times(AtMost(1))
|
|
.WillRepeatedly(Return());
|
|
EXPECT_FALSE(parser.Parse("reg: expr1 : expr2"));
|
|
}
|
|
|
|
TEST_F(Parser, RuleLoneColon) {
|
|
- EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "expr"))
|
|
.Times(AtMost(1))
|
|
.WillRepeatedly(Return());
|
|
EXPECT_FALSE(parser.Parse(" r1: expr :"));
|
|
}
|
|
|
|
TEST_F(Parser, RegNoExprRule) {
|
|
- EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
|
|
+ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "expr"))
|
|
.Times(AtMost(1))
|
|
.WillRepeatedly(Return());
|
|
EXPECT_FALSE(parser.Parse("r0: r1: expr"));
|
|
}
|
|
|
|
class ParseHandlerFixture: public CFIFixture {
|
|
public:
|
|
ParseHandlerFixture() : CFIFixture(), handler(&cfi) { }
|
|
CFIFrameInfoParseHandler handler;
|
|
};
|
|
|
|
class ParseHandler: public ParseHandlerFixture, public Test { };
|
|
|
|
TEST_F(ParseHandler, CFARARule) {
|
|
handler.CFARule("reg-for-cfa");
|
|
handler.RARule("reg-for-ra");
|
|
- registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
|
|
- registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
|
|
+ registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
|
|
+ registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
- ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
|
|
- ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
|
|
+ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
|
|
+ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
|
|
}
|
|
|
|
TEST_F(ParseHandler, RegisterRules) {
|
|
handler.CFARule("reg-for-cfa");
|
|
handler.RARule("reg-for-ra");
|
|
- handler.RegisterRule("reg1", "reg-for-reg1");
|
|
- handler.RegisterRule("reg2", "reg-for-reg2");
|
|
- registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
|
|
- registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
|
|
- registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL;
|
|
- registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL;
|
|
+ handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1");
|
|
+ handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2");
|
|
+ registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
|
|
+ registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
|
|
+ registers[ToUniqueString("reg-for-reg1")] = 0x06cde8e2ff062481ULL;
|
|
+ registers[ToUniqueString("reg-for-reg2")] = 0xff0c4f76403173e2ULL;
|
|
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
|
|
&caller_registers));
|
|
- ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
|
|
- ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
|
|
- ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]);
|
|
- ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]);
|
|
+ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
|
|
+ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
|
|
+ ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers[ToUniqueString("reg1")]);
|
|
+ ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers[ToUniqueString("reg2")]);
|
|
}
|
|
|
|
struct SimpleCFIWalkerFixture {
|
|
struct RawContext {
|
|
uint64_t r0, r1, r2, r3, r4, sp, pc;
|
|
};
|
|
enum Validity {
|
|
R0_VALID = 0x01,
|
|
@@ -475,23 +493,23 @@
|
|
CFIFrameInfo call_frame_info;
|
|
CFIWalker walker;
|
|
MockMemoryRegion memory;
|
|
RawContext callee_context, caller_context;
|
|
};
|
|
|
|
SimpleCFIWalkerFixture::CFIWalker::RegisterSet
|
|
SimpleCFIWalkerFixture::register_map[7] = {
|
|
- { "r0", NULL, true, R0_VALID, &RawContext::r0 },
|
|
- { "r1", NULL, true, R1_VALID, &RawContext::r1 },
|
|
- { "r2", NULL, false, R2_VALID, &RawContext::r2 },
|
|
- { "r3", NULL, false, R3_VALID, &RawContext::r3 },
|
|
- { "r4", NULL, true, R4_VALID, &RawContext::r4 },
|
|
- { "sp", ".cfa", true, SP_VALID, &RawContext::sp },
|
|
- { "pc", ".ra", true, PC_VALID, &RawContext::pc },
|
|
+ { ToUniqueString("r0"), NULL, true, R0_VALID, &RawContext::r0 },
|
|
+ { ToUniqueString("r1"), NULL, true, R1_VALID, &RawContext::r1 },
|
|
+ { ToUniqueString("r2"), NULL, false, R2_VALID, &RawContext::r2 },
|
|
+ { ToUniqueString("r3"), NULL, false, R3_VALID, &RawContext::r3 },
|
|
+ { ToUniqueString("r4"), NULL, true, R4_VALID, &RawContext::r4 },
|
|
+ { ToUniqueString("sp"), ustr__ZDcfa(), true, SP_VALID, &RawContext::sp },
|
|
+ { ToUniqueString("pc"), ustr__ZDra(), true, PC_VALID, &RawContext::pc },
|
|
};
|
|
|
|
class SimpleWalker: public SimpleCFIWalkerFixture, public Test { };
|
|
|
|
TEST_F(SimpleWalker, Walk) {
|
|
// Stack_top is the current stack pointer, pointing to the lowest
|
|
// address of a frame that looks like this (all 64-bit words):
|
|
//
|
|
@@ -516,18 +534,20 @@
|
|
// Saved return address.
|
|
EXPECT_CALL(memory,
|
|
GetMemoryAtAddress(stack_top + 16, A<uint64_t *>()))
|
|
.WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL),
|
|
Return(true)));
|
|
|
|
call_frame_info.SetCFARule(Module::Expr("sp 24 +"));
|
|
call_frame_info.SetRARule(Module::Expr(".cfa 8 - ^"));
|
|
- call_frame_info.SetRegisterRule("r0", Module::Expr(".cfa 24 - ^"));
|
|
- call_frame_info.SetRegisterRule("r1", Module::Expr("r2"));
|
|
+ call_frame_info.SetRegisterRule(ToUniqueString("r0"),
|
|
+ Module::Expr(".cfa 24 - ^"));
|
|
+ call_frame_info.SetRegisterRule(ToUniqueString("r1"),
|
|
+ Module::Expr("r2"));
|
|
|
|
callee_context.r0 = 0x94e030ca79edd119ULL;
|
|
callee_context.r1 = 0x937b4d7e95ce52d9ULL;
|
|
callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1
|
|
// callee_context.r3 is not valid in callee.
|
|
// callee_context.r4 is not valid in callee.
|
|
callee_context.sp = stack_top;
|
|
callee_context.pc = 0x25b21b224311d280ULL;
|
|
diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
|
|
--- a/src/processor/fast_source_line_resolver_unittest.cc
|
|
+++ b/src/processor/fast_source_line_resolver_unittest.cc
|
|
@@ -51,25 +51,34 @@
|
|
#include "processor/module_serializer.h"
|
|
#include "processor/module_comparer.h"
|
|
|
|
namespace {
|
|
|
|
using google_breakpad::SourceLineResolverBase;
|
|
using google_breakpad::BasicSourceLineResolver;
|
|
using google_breakpad::FastSourceLineResolver;
|
|
+using google_breakpad::FromUniqueString;
|
|
using google_breakpad::ModuleSerializer;
|
|
using google_breakpad::ModuleComparer;
|
|
using google_breakpad::CFIFrameInfo;
|
|
using google_breakpad::CodeModule;
|
|
using google_breakpad::MemoryRegion;
|
|
using google_breakpad::StackFrame;
|
|
+using google_breakpad::ToUniqueString;
|
|
using google_breakpad::WindowsFrameInfo;
|
|
using google_breakpad::linked_ptr;
|
|
using google_breakpad::scoped_ptr;
|
|
+using google_breakpad::ustr__ZDcfa;
|
|
+using google_breakpad::ustr__ZDra;
|
|
+using google_breakpad::ustr__ZSebx;
|
|
+using google_breakpad::ustr__ZSebp;
|
|
+using google_breakpad::ustr__ZSedi;
|
|
+using google_breakpad::ustr__ZSesi;
|
|
+using google_breakpad::ustr__ZSesp;
|
|
|
|
class TestCodeModule : public CodeModule {
|
|
public:
|
|
explicit TestCodeModule(string code_file) : code_file_(code_file) {}
|
|
virtual ~TestCodeModule() {}
|
|
|
|
virtual uint64_t base_address() const { return 0; }
|
|
virtual uint64_t size() const { return 0xb000; }
|
|
@@ -119,34 +128,34 @@
|
|
// association. (That is, ACTUAL's associations should be a subset of
|
|
// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
|
|
// ".cfa".
|
|
static bool VerifyRegisters(
|
|
const char *file, int line,
|
|
const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
|
|
const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
|
|
CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
|
|
- a = actual.find(".cfa");
|
|
+ a = actual.find(ustr__ZDcfa());
|
|
if (a == actual.end())
|
|
return false;
|
|
- a = actual.find(".ra");
|
|
+ a = actual.find(ustr__ZDra());
|
|
if (a == actual.end())
|
|
return false;
|
|
for (a = actual.begin(); a != actual.end(); a++) {
|
|
CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
|
|
expected.find(a->first);
|
|
if (e == expected.end()) {
|
|
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
|
|
- file, line, a->first.c_str(), a->second);
|
|
+ file, line, FromUniqueString(a->first), a->second);
|
|
return false;
|
|
}
|
|
if (e->second != a->second) {
|
|
fprintf(stderr,
|
|
"%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
|
|
- file, line, a->first.c_str(), a->second, e->second);
|
|
+ file, line, FromUniqueString(a->first), a->second, e->second);
|
|
return false;
|
|
}
|
|
// Don't complain if this doesn't recover all registers. Although
|
|
// the DWARF spec says that unmentioned registers are undefined,
|
|
// GCC uses omission to mean that they are unchanged.
|
|
}
|
|
return true;
|
|
}
|
|
@@ -282,81 +291,81 @@
|
|
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
|
|
MockMemoryRegion memory;
|
|
|
|
// Regardless of which instruction evaluation takes place at, it
|
|
// should produce the same values for the caller's registers.
|
|
- expected_caller_registers[".cfa"] = 0x1001c;
|
|
- expected_caller_registers[".ra"] = 0xf6438648;
|
|
- expected_caller_registers["$ebp"] = 0x10038;
|
|
- expected_caller_registers["$ebx"] = 0x98ecadc3;
|
|
- expected_caller_registers["$esi"] = 0x878f7524;
|
|
- expected_caller_registers["$edi"] = 0x6312f9a5;
|
|
+ expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
|
|
+ expected_caller_registers[ustr__ZDra()] = 0xf6438648;
|
|
+ expected_caller_registers[ustr__ZSebp()] = 0x10038;
|
|
+ expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
+ expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
|
|
+ expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
|
|
|
|
frame.instruction = 0x3d40;
|
|
frame.module = &module1;
|
|
current_registers.clear();
|
|
- current_registers["$esp"] = 0x10018;
|
|
- current_registers["$ebp"] = 0x10038;
|
|
- current_registers["$ebx"] = 0x98ecadc3;
|
|
- current_registers["$esi"] = 0x878f7524;
|
|
- current_registers["$edi"] = 0x6312f9a5;
|
|
+ current_registers[ustr__ZSesp()] = 0x10018;
|
|
+ current_registers[ustr__ZSebp()] = 0x10038;
|
|
+ current_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
+ current_registers[ustr__ZSesi()] = 0x878f7524;
|
|
+ current_registers[ustr__ZSedi()] = 0x6312f9a5;
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers));
|
|
|
|
frame.instruction = 0x3d41;
|
|
- current_registers["$esp"] = 0x10014;
|
|
+ current_registers[ustr__ZSesp()] = 0x10014;
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers));
|
|
|
|
frame.instruction = 0x3d43;
|
|
- current_registers["$ebp"] = 0x10014;
|
|
+ current_registers[ustr__ZSebp()] = 0x10014;
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
frame.instruction = 0x3d54;
|
|
- current_registers["$ebx"] = 0x6864f054U;
|
|
+ current_registers[ustr__ZSebx()] = 0x6864f054U;
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
frame.instruction = 0x3d5a;
|
|
- current_registers["$esi"] = 0x6285f79aU;
|
|
+ current_registers[ustr__ZSesi()] = 0x6285f79aU;
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
frame.instruction = 0x3d84;
|
|
- current_registers["$edi"] = 0x64061449U;
|
|
+ current_registers[ustr__ZSedi()] = 0x64061449U;
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
->FindCallerRegs<uint32_t>(current_registers, memory,
|
|
&caller_registers));
|
|
VerifyRegisters(__FILE__, __LINE__,
|
|
expected_caller_registers, caller_registers);
|
|
|
|
diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h
|
|
--- a/src/processor/postfix_evaluator-inl.h
|
|
+++ b/src/processor/postfix_evaluator-inl.h
|
|
@@ -51,23 +51,25 @@
|
|
namespace google_breakpad {
|
|
|
|
using std::istringstream;
|
|
using std::ostringstream;
|
|
|
|
|
|
// A small class used in Evaluate to make sure to clean up the stack
|
|
// before returning failure.
|
|
+template<typename ValueType>
|
|
class AutoStackClearer {
|
|
public:
|
|
- explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {}
|
|
+ explicit AutoStackClearer(vector<StackElem<ValueType> > *stack)
|
|
+ : stack_(stack) {}
|
|
~AutoStackClearer() { stack_->clear(); }
|
|
|
|
private:
|
|
- vector<string> *stack_;
|
|
+ vector<StackElem<ValueType> > *stack_;
|
|
};
|
|
|
|
|
|
template<typename ValueType>
|
|
bool PostfixEvaluator<ValueType>::EvaluateToken(
|
|
const string &token,
|
|
const string &expression,
|
|
DictionaryValidityType *assigned) {
|
|
@@ -170,38 +172,57 @@
|
|
BPLOG(INFO) << "Could not PopValue to get value to assign: " <<
|
|
expression;
|
|
return false;
|
|
}
|
|
|
|
// Assignment is only meaningful when assigning into an identifier.
|
|
// The identifier must name a variable, not a constant. Variables
|
|
// begin with '$'.
|
|
- string identifier;
|
|
+ const UniqueString* identifier;
|
|
if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) {
|
|
BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an "
|
|
"identifier is needed to assign " <<
|
|
HexString(value) << ": " << expression;
|
|
return false;
|
|
}
|
|
- if (identifier.empty() || identifier[0] != '$') {
|
|
+ if (identifier == ustr__empty() || Index(identifier,0) != '$') {
|
|
BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " <<
|
|
identifier << ": " << expression;
|
|
return false;
|
|
}
|
|
|
|
(*dictionary_)[identifier] = value;
|
|
if (assigned)
|
|
(*assigned)[identifier] = true;
|
|
} else {
|
|
- // The token is not an operator, it's a literal value or an identifier.
|
|
- // Push it onto the stack as-is. Use push_back instead of PushValue
|
|
- // because PushValue pushes ValueType as a string, but token is already
|
|
- // a string.
|
|
- stack_.push_back(token);
|
|
+ // Push it onto the stack as-is, but first convert it either to a
|
|
+ // ValueType (if a literal) or to a UniqueString* (if an identifier).
|
|
+ //
|
|
+ // First, try to treat the value as a literal. Literals may have leading
|
|
+ // '-' sign, and the entire remaining string must be parseable as
|
|
+ // ValueType. If this isn't possible, it can't be a literal, so treat it
|
|
+ // as an identifier instead.
|
|
+ //
|
|
+ // Some versions of the libstdc++, the GNU standard C++ library, have
|
|
+ // stream extractors for unsigned integer values that permit a leading
|
|
+ // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we
|
|
+ // handle it explicitly here.
|
|
+ istringstream token_stream(token);
|
|
+ ValueType literal = ValueType();
|
|
+ bool negative = false;
|
|
+ if (token_stream.peek() == '-') {
|
|
+ negative = true;
|
|
+ token_stream.get();
|
|
+ }
|
|
+ if (token_stream >> literal && token_stream.peek() == EOF) {
|
|
+ PushValue(negative ? (-literal) : literal);
|
|
+ } else {
|
|
+ PushIdentifier(ToUniqueString(token));
|
|
+ }
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<typename ValueType>
|
|
bool PostfixEvaluator<ValueType>::EvaluateInternal(
|
|
const string &expression,
|
|
DictionaryValidityType *assigned) {
|
|
@@ -236,17 +257,17 @@
|
|
// The expression is being exevaluated only for its side effects. Skip
|
|
// expressions that denote values only.
|
|
if (expr.how_ != Module::kExprPostfix) {
|
|
BPLOG(ERROR) << "Can't evaluate for side-effects: " << expr;
|
|
return false;
|
|
}
|
|
|
|
// Ensure that the stack is cleared before returning.
|
|
- AutoStackClearer clearer(&stack_);
|
|
+ AutoStackClearer<ValueType> clearer(&stack_);
|
|
|
|
if (!EvaluateInternal(expr.postfix_, assigned))
|
|
return false;
|
|
|
|
// If there's anything left on the stack, it indicates incomplete execution.
|
|
// This is a failure case. If the stack is empty, evalution was complete
|
|
// and successful.
|
|
if (stack_.empty())
|
|
@@ -260,17 +281,17 @@
|
|
bool PostfixEvaluator<ValueType>::EvaluateForValue(const Module::Expr& expr,
|
|
ValueType* result) {
|
|
switch (expr.how_) {
|
|
|
|
// Postfix expression. Give to the evaluator and return the
|
|
// one-and-only stack element that should be left over.
|
|
case Module::kExprPostfix: {
|
|
// Ensure that the stack is cleared before returning.
|
|
- AutoStackClearer clearer(&stack_);
|
|
+ AutoStackClearer<ValueType> clearer(&stack_);
|
|
|
|
if (!EvaluateInternal(expr.postfix_, NULL))
|
|
return false;
|
|
|
|
// A successful execution should leave exactly one value on the stack.
|
|
if (stack_.size() != 1) {
|
|
BPLOG(ERROR) << "Expression yielded bad number of results: "
|
|
<< "'" << expr << "'";
|
|
@@ -314,77 +335,56 @@
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
template<typename ValueType>
|
|
typename PostfixEvaluator<ValueType>::PopResult
|
|
PostfixEvaluator<ValueType>::PopValueOrIdentifier(
|
|
- ValueType *value, string *identifier) {
|
|
+ ValueType *value, const UniqueString** identifier) {
|
|
// There needs to be at least one element on the stack to pop.
|
|
if (!stack_.size())
|
|
return POP_RESULT_FAIL;
|
|
|
|
- string token = stack_.back();
|
|
+ StackElem<ValueType> el = stack_.back();
|
|
stack_.pop_back();
|
|
|
|
- // First, try to treat the value as a literal. Literals may have leading
|
|
- // '-' sign, and the entire remaining string must be parseable as
|
|
- // ValueType. If this isn't possible, it can't be a literal, so treat it
|
|
- // as an identifier instead.
|
|
- //
|
|
- // Some versions of the libstdc++, the GNU standard C++ library, have
|
|
- // stream extractors for unsigned integer values that permit a leading
|
|
- // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we
|
|
- // handle it explicitly here.
|
|
- istringstream token_stream(token);
|
|
- ValueType literal = ValueType();
|
|
- bool negative;
|
|
- if (token_stream.peek() == '-') {
|
|
- negative = true;
|
|
- token_stream.get();
|
|
- } else {
|
|
- negative = false;
|
|
- }
|
|
- if (token_stream >> literal && token_stream.peek() == EOF) {
|
|
- if (value) {
|
|
- *value = literal;
|
|
- }
|
|
- if (negative)
|
|
- *value = -*value;
|
|
+ if (el.isValue) {
|
|
+ if (value)
|
|
+ *value = el.u.val;
|
|
return POP_RESULT_VALUE;
|
|
} else {
|
|
- if (identifier) {
|
|
- *identifier = token;
|
|
- }
|
|
+ if (identifier)
|
|
+ *identifier = el.u.ustr;
|
|
return POP_RESULT_IDENTIFIER;
|
|
}
|
|
}
|
|
|
|
|
|
template<typename ValueType>
|
|
bool PostfixEvaluator<ValueType>::PopValue(ValueType *value) {
|
|
ValueType literal = ValueType();
|
|
- string token;
|
|
+ const UniqueString* token;
|
|
PopResult result;
|
|
if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) {
|
|
return false;
|
|
} else if (result == POP_RESULT_VALUE) {
|
|
// This is the easy case.
|
|
*value = literal;
|
|
} else { // result == POP_RESULT_IDENTIFIER
|
|
// There was an identifier at the top of the stack. Resolve it to a
|
|
// value by looking it up in the dictionary.
|
|
typename DictionaryType::const_iterator iterator =
|
|
dictionary_->find(token);
|
|
if (iterator == dictionary_->end()) {
|
|
// The identifier wasn't found in the dictionary. Don't imply any
|
|
// default value, just fail.
|
|
- BPLOG(INFO) << "Identifier " << token << " not in dictionary";
|
|
+ BPLOG(INFO) << "Identifier " << FromUniqueString(token)
|
|
+ << " not in dictionary";
|
|
return false;
|
|
}
|
|
|
|
*value = iterator->second;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
@@ -394,18 +394,23 @@
|
|
bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1,
|
|
ValueType *value2) {
|
|
return PopValue(value2) && PopValue(value1);
|
|
}
|
|
|
|
|
|
template<typename ValueType>
|
|
void PostfixEvaluator<ValueType>::PushValue(const ValueType &value) {
|
|
- ostringstream token_stream;
|
|
- token_stream << value;
|
|
- stack_.push_back(token_stream.str());
|
|
+ StackElem<ValueType> el(value);
|
|
+ stack_.push_back(el);
|
|
+}
|
|
+
|
|
+template<typename ValueType>
|
|
+void PostfixEvaluator<ValueType>::PushIdentifier(const UniqueString* str) {
|
|
+ StackElem<ValueType> el(str);
|
|
+ stack_.push_back(el);
|
|
}
|
|
|
|
|
|
} // namespace google_breakpad
|
|
|
|
|
|
#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__
|
|
diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
|
|
--- a/src/processor/postfix_evaluator.h
|
|
+++ b/src/processor/postfix_evaluator.h
|
|
@@ -70,30 +70,41 @@
|
|
#define PROCESSOR_POSTFIX_EVALUATOR_H__
|
|
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "common/using_std_string.h"
|
|
+#include "common/unique_string.h"
|
|
#include "common/module.h"
|
|
|
|
namespace google_breakpad {
|
|
|
|
using std::map;
|
|
using std::vector;
|
|
|
|
class MemoryRegion;
|
|
|
|
+// A union type for elements in the postfix evaluator's stack.
|
|
+template<typename ValueType>
|
|
+class StackElem {
|
|
+ public:
|
|
+ StackElem(ValueType val) { isValue = true; u.val = val; }
|
|
+ StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; }
|
|
+ bool isValue;
|
|
+ union { ValueType val; const UniqueString* ustr; } u;
|
|
+};
|
|
+
|
|
template<typename ValueType>
|
|
class PostfixEvaluator {
|
|
public:
|
|
- typedef map<string, ValueType> DictionaryType;
|
|
- typedef map<string, bool> DictionaryValidityType;
|
|
+ typedef map<const UniqueString*, ValueType> DictionaryType;
|
|
+ typedef map<const UniqueString*, bool> DictionaryValidityType;
|
|
|
|
// Create a PostfixEvaluator object that may be used (with Evaluate) on
|
|
// one or more expressions. PostfixEvaluator does not take ownership of
|
|
// either argument. |memory| may be NULL, in which case dereferencing
|
|
// (^) will not be supported. |dictionary| may be NULL, but evaluation
|
|
// will fail in that case unless set_dictionary is used before calling
|
|
// Evaluate.
|
|
PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory)
|
|
@@ -128,24 +139,28 @@
|
|
};
|
|
|
|
// Retrieves the topmost literal value, constant, or variable from the
|
|
// stack. Returns POP_RESULT_VALUE if the topmost entry is a literal
|
|
// value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER
|
|
// if the topmost entry is a constant or variable identifier, and sets
|
|
// |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such
|
|
// as when the stack is empty.
|
|
- PopResult PopValueOrIdentifier(ValueType *value, string *identifier);
|
|
+ PopResult PopValueOrIdentifier(ValueType *value,
|
|
+ const UniqueString** identifier);
|
|
|
|
// Retrieves the topmost value on the stack. If the topmost entry is
|
|
// an identifier, the dictionary is queried for the identifier's value.
|
|
// Returns false on failure, such as when the stack is empty or when
|
|
// a nonexistent identifier is named.
|
|
bool PopValue(ValueType *value);
|
|
|
|
+ // Pushes a UniqueString* on the stack.
|
|
+ void PushIdentifier(const UniqueString* ustr);
|
|
+
|
|
// Retrieves the top two values on the stack, in the style of PopValue.
|
|
// value2 is popped before value1, so that value1 corresponds to the
|
|
// entry that was pushed prior to value2. Returns false on failure.
|
|
bool PopValues(ValueType *value1, ValueType *value2);
|
|
|
|
// Pushes a new value onto the stack.
|
|
void PushValue(const ValueType &value);
|
|
|
|
@@ -166,15 +181,15 @@
|
|
|
|
// If non-NULL, the MemoryRegion used for dereference (^) operations.
|
|
// If NULL, dereferencing is unsupported and will fail. Weak pointer.
|
|
const MemoryRegion *memory_;
|
|
|
|
// The stack contains state information as execution progresses. Values
|
|
// are pushed on to it as the expression string is read and as operations
|
|
// yield values; values are popped when used as operands to operators.
|
|
- vector<string> stack_;
|
|
+ vector<StackElem<ValueType> > stack_;
|
|
};
|
|
|
|
} // namespace google_breakpad
|
|
|
|
|
|
#endif // PROCESSOR_POSTFIX_EVALUATOR_H__
|
|
diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
|
|
--- a/src/processor/postfix_evaluator_unittest.cc
|
|
+++ b/src/processor/postfix_evaluator_unittest.cc
|
|
@@ -43,18 +43,32 @@
|
|
#include "google_breakpad/processor/memory_region.h"
|
|
#include "processor/logging.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
using std::map;
|
|
+using google_breakpad::FromUniqueString;
|
|
using google_breakpad::MemoryRegion;
|
|
using google_breakpad::PostfixEvaluator;
|
|
+using google_breakpad::ToUniqueString;
|
|
+using google_breakpad::UniqueString;
|
|
+using google_breakpad::ustr__ZDcbParams;
|
|
+using google_breakpad::ustr__ZDcbSavedRegs;
|
|
+using google_breakpad::ustr__ZDcfa;
|
|
+using google_breakpad::ustr__ZDra;
|
|
+using google_breakpad::ustr__ZDraSearchStart;
|
|
+using google_breakpad::ustr__ZSebx;
|
|
+using google_breakpad::ustr__ZSebp;
|
|
+using google_breakpad::ustr__ZSedi;
|
|
+using google_breakpad::ustr__ZSeip;
|
|
+using google_breakpad::ustr__ZSesi;
|
|
+using google_breakpad::ustr__ZSesp;
|
|
|
|
|
|
// FakeMemoryRegion is used to test PostfixEvaluator's dereference (^)
|
|
// operator. The result of dereferencing a value is one greater than
|
|
// the value.
|
|
class FakeMemoryRegion : public MemoryRegion {
|
|
public:
|
|
virtual uint64_t GetBase() const { return 0; }
|
|
@@ -95,17 +109,17 @@
|
|
// The list of tests.
|
|
const EvaluateTest *evaluate_tests;
|
|
|
|
// The number of tests.
|
|
unsigned int evaluate_test_count;
|
|
|
|
// Identifiers and their expected values upon completion of the Evaluate
|
|
// tests in the set.
|
|
- map<string, unsigned int> *validate_data;
|
|
+ map<const UniqueString*, unsigned int> *validate_data;
|
|
};
|
|
|
|
|
|
struct EvaluateForValueTest {
|
|
// Expression passed to PostfixEvaluator::Evaluate.
|
|
const string expression;
|
|
|
|
// True if the expression is expected to be evaluable, false if evaluation
|
|
@@ -147,39 +161,39 @@
|
|
{ "$rMul 9 6 * =", true }, // $rMul = 9 * 6 = 54
|
|
{ "$rSub 9 6 - =", true }, // $rSub = 9 - 6 = 3
|
|
{ "$rDivQ 9 6 / =", true }, // $rDivQ = 9 / 6 = 1
|
|
{ "$rDivM 9 6 % =", true }, // $rDivM = 9 % 6 = 3
|
|
{ "$rDeref 9 ^ =", true }, // $rDeref = ^9 = 10 (FakeMemoryRegion)
|
|
{ "$rAlign 36 8 @ =", true }, // $rAlign = 36 @ 8
|
|
{ "$rAdd3 2 2 + =$rMul2 9 6 * =", true } // smashed-equals tokenization
|
|
};
|
|
- map<string, unsigned int> validate_data_0;
|
|
- validate_data_0["$rAdd"] = 8;
|
|
- validate_data_0["$rAdd2"] = 4;
|
|
- validate_data_0["$rSub"] = 3;
|
|
- validate_data_0["$rMul"] = 54;
|
|
- validate_data_0["$rDivQ"] = 1;
|
|
- validate_data_0["$rDivM"] = 3;
|
|
- validate_data_0["$rDeref"] = 10;
|
|
- validate_data_0["$rAlign"] = 32;
|
|
- validate_data_0["$rAdd3"] = 4;
|
|
- validate_data_0["$rMul2"] = 54;
|
|
+ map<const UniqueString*, unsigned int> validate_data_0;
|
|
+ validate_data_0[ToUniqueString("$rAdd")] = 8;
|
|
+ validate_data_0[ToUniqueString("$rAdd2")] = 4;
|
|
+ validate_data_0[ToUniqueString("$rSub")] = 3;
|
|
+ validate_data_0[ToUniqueString("$rMul")] = 54;
|
|
+ validate_data_0[ToUniqueString("$rDivQ")] = 1;
|
|
+ validate_data_0[ToUniqueString("$rDivM")] = 3;
|
|
+ validate_data_0[ToUniqueString("$rDeref")] = 10;
|
|
+ validate_data_0[ToUniqueString("$rAlign")] = 32;
|
|
+ validate_data_0[ToUniqueString("$rAdd3")] = 4;
|
|
+ validate_data_0[ToUniqueString("$rMul2")] = 54;
|
|
|
|
// The second test set simulates a couple of MSVC program strings.
|
|
// The data is fudged a little bit because the tests use FakeMemoryRegion
|
|
// instead of a real stack snapshot, but the program strings are real and
|
|
// the implementation doesn't know or care that the data is not real.
|
|
PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
|
|
- dictionary_1["$ebp"] = 0xbfff0010;
|
|
- dictionary_1["$eip"] = 0x10000000;
|
|
- dictionary_1["$esp"] = 0xbfff0000;
|
|
- dictionary_1[".cbSavedRegs"] = 4;
|
|
- dictionary_1[".cbParams"] = 4;
|
|
- dictionary_1[".raSearchStart"] = 0xbfff0020;
|
|
+ dictionary_1[ustr__ZSebp()] = 0xbfff0010;
|
|
+ dictionary_1[ustr__ZSeip()] = 0x10000000;
|
|
+ dictionary_1[ustr__ZSesp()] = 0xbfff0000;
|
|
+ dictionary_1[ustr__ZDcbSavedRegs()] = 4;
|
|
+ dictionary_1[ustr__ZDcbParams()] = 4;
|
|
+ dictionary_1[ustr__ZDraSearchStart()] = 0xbfff0020;
|
|
const EvaluateTest evaluate_tests_1[] = {
|
|
{ "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
|
|
"$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
|
|
// Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015,
|
|
// $ebp = 0xbfff0011, $esp = 0xbfff0018,
|
|
// $L = 0xbfff000c, $P = 0xbfff001c
|
|
{ "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
|
|
"$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =",
|
|
@@ -188,28 +202,28 @@
|
|
// $ebp = 0xbfff0012, $esp = 0xbfff0019,
|
|
// $L = 0xbfff000d, $P = 0xbfff001d,
|
|
// $ebx = 0xbffefff6
|
|
{ "$T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = "
|
|
"$esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = "
|
|
"$ebx $T0 28 - ^ =",
|
|
true }
|
|
};
|
|
- map<string, unsigned int> validate_data_1;
|
|
- validate_data_1["$T0"] = 0xbfff0012;
|
|
- validate_data_1["$T1"] = 0xbfff0020;
|
|
- validate_data_1["$T2"] = 0xbfff0019;
|
|
- validate_data_1["$eip"] = 0xbfff0021;
|
|
- validate_data_1["$ebp"] = 0xbfff0012;
|
|
- validate_data_1["$esp"] = 0xbfff0024;
|
|
- validate_data_1["$L"] = 0xbfff000e;
|
|
- validate_data_1["$P"] = 0xbfff0028;
|
|
- validate_data_1["$ebx"] = 0xbffefff7;
|
|
- validate_data_1[".cbSavedRegs"] = 4;
|
|
- validate_data_1[".cbParams"] = 4;
|
|
+ map<const UniqueString*, unsigned int> validate_data_1;
|
|
+ validate_data_1[ToUniqueString("$T0")] = 0xbfff0012;
|
|
+ validate_data_1[ToUniqueString("$T1")] = 0xbfff0020;
|
|
+ validate_data_1[ToUniqueString("$T2")] = 0xbfff0019;
|
|
+ validate_data_1[ustr__ZSeip()] = 0xbfff0021;
|
|
+ validate_data_1[ustr__ZSebp()] = 0xbfff0012;
|
|
+ validate_data_1[ustr__ZSesp()] = 0xbfff0024;
|
|
+ validate_data_1[ToUniqueString("$L")] = 0xbfff000e;
|
|
+ validate_data_1[ToUniqueString("$P")] = 0xbfff0028;
|
|
+ validate_data_1[ustr__ZSebx()] = 0xbffefff7;
|
|
+ validate_data_1[ustr__ZDcbSavedRegs()] = 4;
|
|
+ validate_data_1[ustr__ZDcbParams()] = 4;
|
|
|
|
EvaluateTestSet evaluate_test_sets[] = {
|
|
{ &dictionary_0, evaluate_tests_0,
|
|
sizeof(evaluate_tests_0) / sizeof(EvaluateTest), &validate_data_0 },
|
|
{ &dictionary_1, evaluate_tests_1,
|
|
sizeof(evaluate_tests_1) / sizeof(EvaluateTest), &validate_data_1 },
|
|
};
|
|
|
|
@@ -251,97 +265,100 @@
|
|
evaluate_test->expression.c_str(),
|
|
evaluate_test->evaluable ? "evaluable" : "not evaluable",
|
|
result ? "evaluted" : "not evaluated");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Validate the results.
|
|
- for (map<string, unsigned int>::const_iterator validate_iterator =
|
|
+ for (map<const UniqueString*, unsigned int>::const_iterator
|
|
+ validate_iterator =
|
|
evaluate_test_set->validate_data->begin();
|
|
validate_iterator != evaluate_test_set->validate_data->end();
|
|
++validate_iterator) {
|
|
- const string identifier = validate_iterator->first;
|
|
+ const UniqueString* identifier = validate_iterator->first;
|
|
unsigned int expected_value = validate_iterator->second;
|
|
|
|
- map<string, unsigned int>::const_iterator dictionary_iterator =
|
|
+ map<const UniqueString*, unsigned int>::const_iterator
|
|
+ dictionary_iterator =
|
|
evaluate_test_set->dictionary->find(identifier);
|
|
|
|
// The identifier must exist in the dictionary.
|
|
if (dictionary_iterator == evaluate_test_set->dictionary->end()) {
|
|
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
|
|
"validate identifier \"%s\", "
|
|
"expected %d, observed not found\n",
|
|
evaluate_test_set_index, evaluate_test_set_count,
|
|
- identifier.c_str(), expected_value);
|
|
+ FromUniqueString(identifier), expected_value);
|
|
return false;
|
|
}
|
|
|
|
// The value in the dictionary must be the same as the expected value.
|
|
unsigned int observed_value = dictionary_iterator->second;
|
|
if (expected_value != observed_value) {
|
|
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
|
|
"validate identifier \"%s\", "
|
|
"expected %d, observed %d\n",
|
|
evaluate_test_set_index, evaluate_test_set_count,
|
|
- identifier.c_str(), expected_value, observed_value);
|
|
+ FromUniqueString(identifier), expected_value, observed_value);
|
|
return false;
|
|
}
|
|
|
|
// The value must be set in the "assigned" dictionary if it was a
|
|
// variable. It must not have been assigned if it was a constant.
|
|
- bool expected_assigned = identifier[0] == '$';
|
|
+ bool expected_assigned = FromUniqueString(identifier)[0] == '$';
|
|
bool observed_assigned = false;
|
|
PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator
|
|
iterator_assigned = assigned.find(identifier);
|
|
if (iterator_assigned != assigned.end()) {
|
|
observed_assigned = iterator_assigned->second;
|
|
}
|
|
if (expected_assigned != observed_assigned) {
|
|
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
|
|
"validate assignment of \"%s\", "
|
|
"expected %d, observed %d\n",
|
|
evaluate_test_set_index, evaluate_test_set_count,
|
|
- identifier.c_str(), expected_assigned, observed_assigned);
|
|
+ FromUniqueString(identifier), expected_assigned,
|
|
+ observed_assigned);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// EvaluateForValue tests.
|
|
PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
|
|
- dictionary_2["$ebp"] = 0xbfff0010;
|
|
- dictionary_2["$eip"] = 0x10000000;
|
|
- dictionary_2["$esp"] = 0xbfff0000;
|
|
- dictionary_2[".cbSavedRegs"] = 4;
|
|
- dictionary_2[".cbParams"] = 4;
|
|
- dictionary_2[".raSearchStart"] = 0xbfff0020;
|
|
+ dictionary_2[ustr__ZSebp()] = 0xbfff0010;
|
|
+ dictionary_2[ustr__ZSeip()] = 0x10000000;
|
|
+ dictionary_2[ustr__ZSesp()] = 0xbfff0000;
|
|
+ dictionary_2[ustr__ZDcbSavedRegs()] = 4;
|
|
+ dictionary_2[ustr__ZDcbParams()] = 4;
|
|
+ dictionary_2[ustr__ZDraSearchStart()] = 0xbfff0020;
|
|
const EvaluateForValueTest evaluate_for_value_tests_2[] = {
|
|
{ "28907223", true, 28907223 }, // simple constant
|
|
{ "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic
|
|
{ "-870245 8769343 +", true, 7899098 }, // negative constants
|
|
{ "$ebp $esp - $eip +", true, 0x10000010 }, // variable references
|
|
{ "18929794 34015074", false, 0 }, // too many values
|
|
{ "$ebp $ebp 4 - =", false, 0 }, // too few values
|
|
{ "$new $eip = $new", true, 0x10000000 }, // make new variable
|
|
{ "$new 4 +", true, 0x10000004 }, // see prior assignments
|
|
{ ".cfa 42 = 10", false, 0 } // can't set constants
|
|
};
|
|
const int evaluate_for_value_tests_2_size
|
|
= (sizeof (evaluate_for_value_tests_2)
|
|
/ sizeof (evaluate_for_value_tests_2[0]));
|
|
- map<string, unsigned int> validate_data_2;
|
|
- validate_data_2["$eip"] = 0x10000000;
|
|
- validate_data_2["$ebp"] = 0xbfff000c;
|
|
- validate_data_2["$esp"] = 0xbfff0000;
|
|
- validate_data_2["$new"] = 0x10000000;
|
|
- validate_data_2[".cbSavedRegs"] = 4;
|
|
- validate_data_2[".cbParams"] = 4;
|
|
- validate_data_2[".raSearchStart"] = 0xbfff0020;
|
|
+ map<const UniqueString*, unsigned int> validate_data_2;
|
|
+ validate_data_2[ustr__ZSeip()] = 0x10000000;
|
|
+ validate_data_2[ustr__ZSebp()] = 0xbfff000c;
|
|
+ validate_data_2[ustr__ZSesp()] = 0xbfff0000;
|
|
+ validate_data_2[ToUniqueString("$new")] = 0x10000000;
|
|
+ validate_data_2[ustr__ZDcbSavedRegs()] = 4;
|
|
+ validate_data_2[ustr__ZDcbParams()] = 4;
|
|
+ validate_data_2[ustr__ZDraSearchStart()] = 0xbfff0020;
|
|
|
|
postfix_evaluator.set_dictionary(&dictionary_2);
|
|
for (int i = 0; i < evaluate_for_value_tests_2_size; i++) {
|
|
const EvaluateForValueTest *test = &evaluate_for_value_tests_2[i];
|
|
unsigned int result;
|
|
if (postfix_evaluator.EvaluateForValue(test->expression, &result)
|
|
!= test->evaluable) {
|
|
fprintf(stderr, "FAIL: evaluate for value test %d, "
|
|
@@ -353,40 +370,43 @@
|
|
if (test->evaluable && result != test->value) {
|
|
fprintf(stderr, "FAIL: evaluate for value test %d, "
|
|
"expected value to be 0x%x, but it was 0x%x\n",
|
|
i, test->value, result);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
- for (map<string, unsigned int>::iterator v = validate_data_2.begin();
|
|
+ for (map<const UniqueString*, unsigned int>::iterator v =
|
|
+ validate_data_2.begin();
|
|
v != validate_data_2.end(); v++) {
|
|
- map<string, unsigned int>::iterator a = dictionary_2.find(v->first);
|
|
+ map<const UniqueString*, unsigned int>::iterator a =
|
|
+ dictionary_2.find(v->first);
|
|
if (a == dictionary_2.end()) {
|
|
fprintf(stderr, "FAIL: evaluate for value dictionary check: "
|
|
"expected dict[\"%s\"] to be 0x%x, but it was unset\n",
|
|
- v->first.c_str(), v->second);
|
|
+ FromUniqueString(v->first), v->second);
|
|
return false;
|
|
} else if (a->second != v->second) {
|
|
fprintf(stderr, "FAIL: evaluate for value dictionary check: "
|
|
"expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
|
|
- v->first.c_str(), v->second, a->second);
|
|
+ FromUniqueString(v->first), v->second, a->second);
|
|
return false;
|
|
}
|
|
dictionary_2.erase(a);
|
|
}
|
|
|
|
- map<string, unsigned int>::iterator remaining = dictionary_2.begin();
|
|
+ map<const UniqueString*, unsigned int>::iterator remaining =
|
|
+ dictionary_2.begin();
|
|
if (remaining != dictionary_2.end()) {
|
|
fprintf(stderr, "FAIL: evaluation of test expressions put unexpected "
|
|
"values in dictionary:\n");
|
|
for (; remaining != dictionary_2.end(); remaining++)
|
|
fprintf(stderr, " dict[\"%s\"] == 0x%x\n",
|
|
- remaining->first.c_str(), remaining->second);
|
|
+ FromUniqueString(remaining->first), remaining->second);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
} // namespace
|
|
diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc
|
|
--- a/src/processor/stackwalker_amd64.cc
|
|
+++ b/src/processor/stackwalker_amd64.cc
|
|
@@ -50,49 +50,49 @@
|
|
|
|
const StackwalkerAMD64::CFIWalker::RegisterSet
|
|
StackwalkerAMD64::cfi_register_map_[] = {
|
|
// It may seem like $rip and $rsp are callee-saves, because the callee is
|
|
// responsible for having them restored upon return. But the callee_saves
|
|
// flags here really means that the walker should assume they're
|
|
// unchanged if the CFI doesn't mention them --- clearly wrong for $rip
|
|
// and $rsp.
|
|
- { "$rax", NULL, false,
|
|
+ { ToUniqueString("$rax"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax },
|
|
- { "$rdx", NULL, false,
|
|
+ { ToUniqueString("$rdx"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx },
|
|
- { "$rcx", NULL, false,
|
|
+ { ToUniqueString("$rcx"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx },
|
|
- { "$rbx", NULL, true,
|
|
+ { ToUniqueString("$rbx"), NULL, true,
|
|
StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx },
|
|
- { "$rsi", NULL, false,
|
|
+ { ToUniqueString("$rsi"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi },
|
|
- { "$rdi", NULL, false,
|
|
+ { ToUniqueString("$rdi"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi },
|
|
- { "$rbp", NULL, true,
|
|
+ { ToUniqueString("$rbp"), NULL, true,
|
|
StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp },
|
|
- { "$rsp", ".cfa", false,
|
|
+ { ToUniqueString("$rsp"), ToUniqueString(".cfa"), false,
|
|
StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp },
|
|
- { "$r8", NULL, false,
|
|
+ { ToUniqueString("$r8"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_R8, &MDRawContextAMD64::r8 },
|
|
- { "$r9", NULL, false,
|
|
+ { ToUniqueString("$r9"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_R9, &MDRawContextAMD64::r9 },
|
|
- { "$r10", NULL, false,
|
|
+ { ToUniqueString("$r10"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 },
|
|
- { "$r11", NULL, false,
|
|
+ { ToUniqueString("$r11"), NULL, false,
|
|
StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 },
|
|
- { "$r12", NULL, true,
|
|
+ { ToUniqueString("$r12"), NULL, true,
|
|
StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 },
|
|
- { "$r13", NULL, true,
|
|
+ { ToUniqueString("$r13"), NULL, true,
|
|
StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 },
|
|
- { "$r14", NULL, true,
|
|
+ { ToUniqueString("$r14"), NULL, true,
|
|
StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 },
|
|
- { "$r15", NULL, true,
|
|
+ { ToUniqueString("$r15"), NULL, true,
|
|
StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 },
|
|
- { "$rip", ".ra", false,
|
|
+ { ToUniqueString("$rip"), ToUniqueString(".ra"), false,
|
|
StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip },
|
|
};
|
|
|
|
StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info,
|
|
const MDRawContextAMD64* context,
|
|
MemoryRegion* memory,
|
|
const CodeModules* modules,
|
|
StackFrameSymbolizer* resolver_helper)
|
|
diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
|
|
--- a/src/processor/stackwalker_arm.cc
|
|
+++ b/src/processor/stackwalker_arm.cc
|
|
@@ -76,21 +76,30 @@
|
|
return frame;
|
|
}
|
|
|
|
StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo(
|
|
const vector<StackFrame*> &frames,
|
|
CFIFrameInfo* cfi_frame_info) {
|
|
StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
|
|
|
|
- static const char* register_names[] = {
|
|
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
|
- "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
|
|
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
|
- "fps", "cpsr",
|
|
+ static const UniqueString *register_names[] = {
|
|
+ ToUniqueString("r0"), ToUniqueString("r1"),
|
|
+ ToUniqueString("r2"), ToUniqueString("r3"),
|
|
+ ToUniqueString("r4"), ToUniqueString("r5"),
|
|
+ ToUniqueString("r6"), ToUniqueString("r7"),
|
|
+ ToUniqueString("r8"), ToUniqueString("r9"),
|
|
+ ToUniqueString("r10"), ToUniqueString("r11"),
|
|
+ ToUniqueString("r12"), ToUniqueString("sp"),
|
|
+ ToUniqueString("lr"), ToUniqueString("pc"),
|
|
+ ToUniqueString("f0"), ToUniqueString("f1"),
|
|
+ ToUniqueString("f2"), ToUniqueString("f3"),
|
|
+ ToUniqueString("f4"), ToUniqueString("f5"),
|
|
+ ToUniqueString("f6"), ToUniqueString("f7"),
|
|
+ ToUniqueString("fps"), ToUniqueString("cpsr"),
|
|
NULL
|
|
};
|
|
|
|
// Populate a dictionary with the valid register values in last_frame.
|
|
CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
|
|
for (int i = 0; register_names[i]; i++)
|
|
if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
|
|
callee_registers[register_names[i]] = last_frame->context.iregs[i];
|
|
@@ -119,17 +128,17 @@
|
|
// Call Standard for the ARM Architecture, which the Linux ABI follows.
|
|
frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
|
|
frame->context.iregs[i] = last_frame->context.iregs[i];
|
|
}
|
|
}
|
|
// If the CFI doesn't recover the PC explicitly, then use .ra.
|
|
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
|
|
CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
|
|
- caller_registers.find(".ra");
|
|
+ caller_registers.find(ustr__ZDra());
|
|
if (entry != caller_registers.end()) {
|
|
if (fp_register_ == -1) {
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
|
|
frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second;
|
|
} else {
|
|
// The CFI updated the link register and not the program counter.
|
|
// Handle getting the program counter from the link register.
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
|
|
@@ -138,17 +147,17 @@
|
|
frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
|
|
last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
|
|
}
|
|
}
|
|
}
|
|
// If the CFI doesn't recover the SP explicitly, then use .cfa.
|
|
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
|
|
CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
|
|
- caller_registers.find(".cfa");
|
|
+ caller_registers.find(ustr__ZDcfa());
|
|
if (entry != caller_registers.end()) {
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP;
|
|
frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second;
|
|
}
|
|
}
|
|
|
|
// If we didn't recover the PC and the SP, then the frame isn't very useful.
|
|
static const int essentials = (StackFrameARM::CONTEXT_VALID_SP
|
|
diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
|
|
--- a/src/processor/stackwalker_x86.cc
|
|
+++ b/src/processor/stackwalker_x86.cc
|
|
@@ -53,33 +53,33 @@
|
|
|
|
const StackwalkerX86::CFIWalker::RegisterSet
|
|
StackwalkerX86::cfi_register_map_[] = {
|
|
// It may seem like $eip and $esp are callee-saves, because (with Unix or
|
|
// cdecl calling conventions) the callee is responsible for having them
|
|
// restored upon return. But the callee_saves flags here really means
|
|
// that the walker should assume they're unchanged if the CFI doesn't
|
|
// mention them, which is clearly wrong for $eip and $esp.
|
|
- { "$eip", ".ra", false,
|
|
+ { ToUniqueString("$eip"), ToUniqueString(".ra"), false,
|
|
StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip },
|
|
- { "$esp", ".cfa", false,
|
|
+ { ToUniqueString("$esp"), ToUniqueString(".cfa"), false,
|
|
StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp },
|
|
- { "$ebp", NULL, true,
|
|
+ { ToUniqueString("$ebp"), NULL, true,
|
|
StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp },
|
|
- { "$eax", NULL, false,
|
|
+ { ToUniqueString("$eax"), NULL, false,
|
|
StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax },
|
|
- { "$ebx", NULL, true,
|
|
+ { ToUniqueString("$ebx"), NULL, true,
|
|
StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx },
|
|
- { "$ecx", NULL, false,
|
|
+ { ToUniqueString("$ecx"), NULL, false,
|
|
StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx },
|
|
- { "$edx", NULL, false,
|
|
+ { ToUniqueString("$edx"), NULL, false,
|
|
StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx },
|
|
- { "$esi", NULL, true,
|
|
+ { ToUniqueString("$esi"), NULL, true,
|
|
StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi },
|
|
- { "$edi", NULL, true,
|
|
+ { ToUniqueString("$edi"), NULL, true,
|
|
StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi },
|
|
};
|
|
|
|
StackwalkerX86::StackwalkerX86(const SystemInfo* system_info,
|
|
const MDRawContextX86* context,
|
|
MemoryRegion* memory,
|
|
const CodeModules* modules,
|
|
StackFrameSymbolizer* resolver_helper)
|
|
@@ -194,26 +194,26 @@
|
|
}
|
|
}
|
|
|
|
// Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used
|
|
// in each program string, and their previous values are known, so set them
|
|
// here.
|
|
PostfixEvaluator<uint32_t>::DictionaryType dictionary;
|
|
// Provide the current register values.
|
|
- dictionary["$ebp"] = last_frame->context.ebp;
|
|
- dictionary["$esp"] = last_frame->context.esp;
|
|
+ dictionary[ustr__ZSebp()] = last_frame->context.ebp;
|
|
+ dictionary[ustr__ZSesp()] = last_frame->context.esp;
|
|
// Provide constants from the debug info for last_frame and its callee.
|
|
// .cbCalleeParams is a Breakpad extension that allows us to use the
|
|
// PostfixEvaluator engine when certain types of debugging information
|
|
// are present without having to write the constants into the program
|
|
// string as literals.
|
|
- dictionary[".cbCalleeParams"] = last_frame_callee_parameter_size;
|
|
- dictionary[".cbSavedRegs"] = last_frame_info->saved_register_size;
|
|
- dictionary[".cbLocals"] = last_frame_info->local_size;
|
|
+ dictionary[ustr__ZDcbCalleeParams()] = last_frame_callee_parameter_size;
|
|
+ dictionary[ustr__ZDcbSavedRegs()] = last_frame_info->saved_register_size;
|
|
+ dictionary[ustr__ZDcbLocals()] = last_frame_info->local_size;
|
|
|
|
uint32_t raSearchStart = last_frame->context.esp +
|
|
last_frame_callee_parameter_size +
|
|
last_frame_info->local_size +
|
|
last_frame_info->saved_register_size;
|
|
|
|
uint32_t raSearchStartOld = raSearchStart;
|
|
uint32_t found = 0; // dummy value
|
|
@@ -232,20 +232,20 @@
|
|
// Skip one slot from the stack and do another scan in order to get the
|
|
// actual return address.
|
|
raSearchStart += 4;
|
|
ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
|
|
}
|
|
|
|
// The difference between raSearch and raSearchStart is unknown,
|
|
// but making them the same seems to work well in practice.
|
|
- dictionary[".raSearchStart"] = raSearchStart;
|
|
- dictionary[".raSearch"] = raSearchStart;
|
|
+ dictionary[ustr__ZDraSearchStart()] = raSearchStart;
|
|
+ dictionary[ustr__ZDraSearch()] = raSearchStart;
|
|
|
|
- dictionary[".cbParams"] = last_frame_info->parameter_size;
|
|
+ dictionary[ustr__ZDcbParams()] = last_frame_info->parameter_size;
|
|
|
|
// Decide what type of program string to use. The program string is in
|
|
// postfix notation and will be passed to PostfixEvaluator::Evaluate.
|
|
// Given the dictionary and the program string, it is possible to compute
|
|
// the return address and the values of other registers in the calling
|
|
// function. Because of bugs described below, the stack may need to be
|
|
// scanned for these values. The results of program string evaluation
|
|
// will be used to determine whether to scan for better values.
|
|
@@ -325,18 +325,18 @@
|
|
}
|
|
|
|
// Now crank it out, making sure that the program string set at least the
|
|
// two required variables.
|
|
PostfixEvaluator<uint32_t> evaluator =
|
|
PostfixEvaluator<uint32_t>(&dictionary, memory_);
|
|
PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity;
|
|
if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
|
|
- dictionary_validity.find("$eip") == dictionary_validity.end() ||
|
|
- dictionary_validity.find("$esp") == dictionary_validity.end()) {
|
|
+ dictionary_validity.find(ustr__ZSeip()) == dictionary_validity.end() ||
|
|
+ dictionary_validity.find(ustr__ZSesp()) == dictionary_validity.end()) {
|
|
// Program string evaluation failed. It may be that %eip is not somewhere
|
|
// with stack frame info, and %ebp is pointing to non-stack memory, so
|
|
// our evaluation couldn't succeed. We'll scan the stack for a return
|
|
// address. This can happen if the stack is in a module for which
|
|
// we don't have symbols, and that module is compiled without a
|
|
// frame pointer.
|
|
uint32_t location_start = last_frame->context.esp;
|
|
uint32_t location, eip;
|
|
@@ -344,69 +344,69 @@
|
|
// if we can't find an instruction pointer even with stack scanning,
|
|
// give up.
|
|
return NULL;
|
|
}
|
|
|
|
// This seems like a reasonable return address. Since program string
|
|
// evaluation failed, use it and set %esp to the location above the
|
|
// one where the return address was found.
|
|
- dictionary["$eip"] = eip;
|
|
- dictionary["$esp"] = location + 4;
|
|
+ dictionary[ustr__ZSeip()] = eip;
|
|
+ dictionary[ustr__ZSesp()] = location + 4;
|
|
trust = StackFrame::FRAME_TRUST_SCAN;
|
|
}
|
|
|
|
// Since this stack frame did not use %ebp in a traditional way,
|
|
// locating the return address isn't entirely deterministic. In that
|
|
// case, the stack can be scanned to locate the return address.
|
|
//
|
|
// However, if program string evaluation resulted in both %eip and
|
|
// %ebp values of 0, trust that the end of the stack has been
|
|
// reached and don't scan for anything else.
|
|
- if (dictionary["$eip"] != 0 || dictionary["$ebp"] != 0) {
|
|
+ if (dictionary[ustr__ZSeip()] != 0 || dictionary[ustr__ZSebp()] != 0) {
|
|
int offset = 0;
|
|
|
|
// This scan can only be done if a CodeModules object is available, to
|
|
// check that candidate return addresses are in fact inside a module.
|
|
//
|
|
// TODO(mmentovai): This ignores dynamically-generated code. One possible
|
|
// solution is to check the minidump's memory map to see if the candidate
|
|
// %eip value comes from a mapped executable page, although this would
|
|
// require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad
|
|
// client doesn't currently write (it would need to call MiniDumpWriteDump
|
|
// with the MiniDumpWithFullMemoryInfo type bit set). Even given this
|
|
// ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
|
|
// an independent execute privilege on memory pages.
|
|
|
|
- uint32_t eip = dictionary["$eip"];
|
|
+ uint32_t eip = dictionary[ustr__ZSeip()];
|
|
if (modules_ && !modules_->GetModuleForAddress(eip)) {
|
|
// The instruction pointer at .raSearchStart was invalid, so start
|
|
// looking one 32-bit word above that location.
|
|
- uint32_t location_start = dictionary[".raSearchStart"] + 4;
|
|
+ uint32_t location_start = dictionary[ustr__ZDraSearchStart()] + 4;
|
|
uint32_t location;
|
|
if (ScanForReturnAddress(location_start, &location, &eip)) {
|
|
// This is a better return address that what program string
|
|
// evaluation found. Use it, and set %esp to the location above the
|
|
// one where the return address was found.
|
|
- dictionary["$eip"] = eip;
|
|
- dictionary["$esp"] = location + 4;
|
|
+ dictionary[ustr__ZSeip()] = eip;
|
|
+ dictionary[ustr__ZSesp()] = location + 4;
|
|
offset = location - location_start;
|
|
trust = StackFrame::FRAME_TRUST_CFI_SCAN;
|
|
}
|
|
}
|
|
|
|
if (recover_ebp) {
|
|
// When trying to recover the previous value of the frame pointer (%ebp),
|
|
// start looking at the lowest possible address in the saved-register
|
|
// area, and look at the entire saved register area, increased by the
|
|
// size of |offset| to account for additional data that may be on the
|
|
// stack. The scan is performed from the highest possible address to
|
|
// the lowest, because the expectation is that the function's prolog
|
|
// would have saved %ebp early.
|
|
- uint32_t ebp = dictionary["$ebp"];
|
|
+ uint32_t ebp = dictionary[ustr__ZSebp()];
|
|
|
|
// When a scan for return address is used, it is possible to skip one or
|
|
// more frames (when return address is not in a known module). One
|
|
// indication for skipped frames is when the value of %ebp is lower than
|
|
// the location of the return address on the stack
|
|
bool has_skipped_frames =
|
|
(trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset);
|
|
|
|
@@ -420,49 +420,49 @@
|
|
location >= location_end;
|
|
location -= 4) {
|
|
if (!memory_->GetMemoryAtAddress(location, &ebp))
|
|
break;
|
|
|
|
if (memory_->GetMemoryAtAddress(ebp, &value)) {
|
|
// The candidate value is a pointer to the same memory region
|
|
// (the stack). Prefer it as a recovered %ebp result.
|
|
- dictionary["$ebp"] = ebp;
|
|
+ dictionary[ustr__ZSebp()] = ebp;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create a new stack frame (ownership will be transferred to the caller)
|
|
// and fill it in.
|
|
StackFrameX86* frame = new StackFrameX86();
|
|
|
|
frame->trust = trust;
|
|
frame->context = last_frame->context;
|
|
- frame->context.eip = dictionary["$eip"];
|
|
- frame->context.esp = dictionary["$esp"];
|
|
- frame->context.ebp = dictionary["$ebp"];
|
|
+ frame->context.eip = dictionary[ustr__ZSeip()];
|
|
+ frame->context.esp = dictionary[ustr__ZSesp()];
|
|
+ frame->context.ebp = dictionary[ustr__ZSebp()];
|
|
frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
|
|
StackFrameX86::CONTEXT_VALID_ESP |
|
|
StackFrameX86::CONTEXT_VALID_EBP;
|
|
|
|
// These are nonvolatile (callee-save) registers, and the program string
|
|
// may have filled them in.
|
|
- if (dictionary_validity.find("$ebx") != dictionary_validity.end()) {
|
|
- frame->context.ebx = dictionary["$ebx"];
|
|
+ if (dictionary_validity.find(ustr__ZSebx()) != dictionary_validity.end()) {
|
|
+ frame->context.ebx = dictionary[ustr__ZSebx()];
|
|
frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX;
|
|
}
|
|
- if (dictionary_validity.find("$esi") != dictionary_validity.end()) {
|
|
- frame->context.esi = dictionary["$esi"];
|
|
+ if (dictionary_validity.find(ustr__ZSesi()) != dictionary_validity.end()) {
|
|
+ frame->context.esi = dictionary[ustr__ZSesi()];
|
|
frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI;
|
|
}
|
|
- if (dictionary_validity.find("$edi") != dictionary_validity.end()) {
|
|
- frame->context.edi = dictionary["$edi"];
|
|
+ if (dictionary_validity.find(ustr__ZSedi()) != dictionary_validity.end()) {
|
|
+ frame->context.edi = dictionary[ustr__ZSedi()];
|
|
frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
|
|
const vector<StackFrame*> &frames,
|
|
diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
|
|
--- a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
|
|
+++ b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
|
|
@@ -98,16 +98,22 @@
|
|
B8C5B51B1166534700D34F4E /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650430B52F6D800611104 /* macho_id.cc */; };
|
|
B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650450B52F6D800611104 /* macho_walker.cc */; };
|
|
B8C5B51D1166534700D34F4E /* dump_syms.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* dump_syms.mm */; };
|
|
B8C5B51E1166534700D34F4E /* dump_syms_tool.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */; };
|
|
B8C5B523116653BA00D34F4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
|
|
D21F97D711CBA12300239E38 /* test_assembler_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D9116CEC0600407530 /* test_assembler_unittest.cc */; };
|
|
D21F97D811CBA13D00239E38 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
|
|
D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; };
|
|
+ D24997CC16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
|
|
+ D24997CD16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
|
|
+ D24997CE16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
|
|
+ D2499A0016B9BA6A00E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
|
|
+ D2499A0216B9BA9600E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
|
|
+ D2499A0316B9BA9D00E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
|
|
/* End PBXBuildFile section */
|
|
|
|
/* Begin PBXContainerItemProxy section */
|
|
8B31051411F100CF00FCF3E4 /* PBXContainerItemProxy */ = {
|
|
isa = PBXContainerItemProxy;
|
|
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
|
proxyType = 1;
|
|
remoteGlobalIDString = D21F97D111CBA0F200239E38;
|
|
@@ -338,16 +344,18 @@
|
|
B89E0E741166575200DD08C9 /* macho_dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_dump; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
B89E0E9511665A6400DD08C9 /* macho_reader_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_reader_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
B89E0E9F11665AC300DD08C9 /* gtest_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtest_main.cc; path = ../../../testing/gtest/src/gtest_main.cc; sourceTree = SOURCE_ROOT; };
|
|
B89E0EA011665AC300DD08C9 /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "../../../testing/gtest/src/gtest-all.cc"; sourceTree = SOURCE_ROOT; };
|
|
B89E0EA311665AEA00DD08C9 /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "../../../testing/src/gmock-all.cc"; sourceTree = SOURCE_ROOT; };
|
|
B8C5B5111166531A00D34F4E /* dump_syms */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dump_syms; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
B8E8CA0C1156C854009E61B2 /* byteswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byteswap.h; path = ../../../common/mac/byteswap.h; sourceTree = SOURCE_ROOT; };
|
|
D21F97D211CBA0F200239E38 /* test_assembler_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_assembler_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
+ D24997CA16B6C16800E588C5 /* unique_string.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = unique_string.cc; path = ../../../common/unique_string.cc; sourceTree = "<group>"; };
|
|
+ D24997CB16B6C16800E588C5 /* unique_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unique_string.h; path = ../../../common/unique_string.h; sourceTree = "<group>"; };
|
|
F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; };
|
|
F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
|
F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; };
|
|
F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; };
|
|
F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
|
F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
|
|
F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; };
|
|
/* End PBXFileReference section */
|
|
@@ -531,16 +539,18 @@
|
|
D21F97D211CBA0F200239E38 /* test_assembler_unittest */,
|
|
);
|
|
name = Products;
|
|
sourceTree = "<group>";
|
|
};
|
|
B88FAE1C11665FFD00407530 /* MODULE */ = {
|
|
isa = PBXGroup;
|
|
children = (
|
|
+ D24997CA16B6C16800E588C5 /* unique_string.cc */,
|
|
+ D24997CB16B6C16800E588C5 /* unique_string.h */,
|
|
B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */,
|
|
B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */,
|
|
B88FB0D6116CEC0600407530 /* dwarf_cu_to_module_unittest.cc */,
|
|
B88FAE201166603300407530 /* dwarf_line_to_module.cc */,
|
|
B88FAE211166603300407530 /* dwarf_line_to_module.h */,
|
|
B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */,
|
|
B88FAE221166603300407530 /* language.cc */,
|
|
B88FAE231166603300407530 /* language.h */,
|
|
@@ -940,16 +950,17 @@
|
|
};
|
|
/* End PBXShellScriptBuildPhase section */
|
|
|
|
/* Begin PBXSourcesBuildPhase section */
|
|
B84A91F1116CF784006C210E /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
+ D2499A0216B9BA9600E588C5 /* unique_string.cc in Sources */,
|
|
B84A91FB116CF7AF006C210E /* module.cc in Sources */,
|
|
B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */,
|
|
B84A91FD116CF7AF006C210E /* stabs_to_module_unittest.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FAF2C116A591D00407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
@@ -983,56 +994,60 @@
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FB0B6116CEABF00407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
B88FB0BD116CEAE000407530 /* module_unittest.cc in Sources */,
|
|
B88FB0C4116CEB4100407530 /* module.cc in Sources */,
|
|
+ D24997CE16B6C16800E588C5 /* unique_string.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FB0DC116CEEA800407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
B88FB0E5116CEED300407530 /* dwarf2diehandler.cc in Sources */,
|
|
B88FB0E6116CEED300407530 /* dwarf2diehandler_unittest.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FB0EF116CEF1900407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
+ D2499A0316B9BA9D00E588C5 /* unique_string.cc in Sources */,
|
|
B88FB0FA116CF00E00407530 /* dwarf_line_to_module.cc in Sources */,
|
|
B88FB0FE116CF02400407530 /* module.cc in Sources */,
|
|
B88FB0FB116CF00E00407530 /* dwarf_line_to_module_unittest.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FB107116CF07900407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
+ D2499A0016B9BA6A00E588C5 /* unique_string.cc in Sources */,
|
|
B88FB112116CF1F000407530 /* dwarf_cu_to_module.cc in Sources */,
|
|
B88FB113116CF1F000407530 /* dwarf_cu_to_module_unittest.cc in Sources */,
|
|
B88FB114116CF1F000407530 /* language.cc in Sources */,
|
|
B88FB115116CF1F000407530 /* module.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FB11C116CF27F00407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
B88FB129116CF2DD00407530 /* module.cc in Sources */,
|
|
B88FB12A116CF2DD00407530 /* dwarf_cfi_to_module.cc in Sources */,
|
|
B88FB12B116CF2DD00407530 /* dwarf_cfi_to_module_unittest.cc in Sources */,
|
|
+ D24997CD16B6C16800E588C5 /* unique_string.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
B88FB132116CF30F00407530 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
B88FB13D116CF38300407530 /* cfi_assembler.cc in Sources */,
|
|
@@ -1086,16 +1101,17 @@
|
|
B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */,
|
|
B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */,
|
|
B88FAE281166603300407530 /* language.cc in Sources */,
|
|
B88FAE291166603300407530 /* module.cc in Sources */,
|
|
B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */,
|
|
B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */,
|
|
B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */,
|
|
4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */,
|
|
+ D24997CC16B6C16800E588C5 /* unique_string.cc in Sources */,
|
|
);
|
|
runOnlyForDeploymentPostprocessing = 0;
|
|
};
|
|
D21F97CF11CBA0F200239E38 /* Sources */ = {
|
|
isa = PBXSourcesBuildPhase;
|
|
buildActionMask = 2147483647;
|
|
files = (
|
|
D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */,
|