tenfourfox/toolkit/crashreporter/breakpad-patches/03-unique-string.patch
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

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 &reg) {
+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 &reg) {
+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 &reg);
+ 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 &reg);
+ 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> &register_names,
+ DwarfCFIToModule(Module *module,
+ const vector<const UniqueString*> &register_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> &register_names_;
+ const vector<const UniqueString*> &register_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 &section)
: Reporter(file, section) { }
MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg));
- MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string &reg));
- MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string &reg));
+ 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, &register_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 &section,
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> &registers,
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 */,