1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/breakpad-patches/03-unique-string.patch Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,4539 @@ 1.4 +# HG changeset patch 1.5 +# User Ted Mielczarek <ted.mielczarek@gmail.com> 1.6 +# Date 1360255134 18000 1.7 +# Thu Feb 07 11:38:54 2013 -0500 1.8 +# Node ID 79cecfef3c2a10d719fe1af9fae2e5257109b028 1.9 +# Parent 08f184a7e6d6d15ecc20abd56bc4e36669c0c68a 1.10 +Rework PostfixEvaluator to use a UniqueString type 1.11 +Patch by Julian Seward <jseward@acm.org>, R=ted 1.12 + 1.13 +diff --git a/Makefile.am b/Makefile.am 1.14 +--- a/Makefile.am 1.15 ++++ b/Makefile.am 1.16 +@@ -134,16 +134,17 @@ 1.17 + src/google_breakpad/processor/source_line_resolver_interface.h \ 1.18 + src/google_breakpad/processor/stack_frame.h \ 1.19 + src/google_breakpad/processor/stack_frame_cpu.h \ 1.20 + src/google_breakpad/processor/stack_frame_symbolizer.h \ 1.21 + src/google_breakpad/processor/stackwalker.h \ 1.22 + src/google_breakpad/processor/symbol_supplier.h \ 1.23 + src/google_breakpad/processor/system_info.h \ 1.24 + src/common/module.cc \ 1.25 ++ src/common/unique_string.cc \ 1.26 + src/processor/address_map-inl.h \ 1.27 + src/processor/address_map.h \ 1.28 + src/processor/basic_code_module.h \ 1.29 + src/processor/basic_code_modules.cc \ 1.30 + src/processor/basic_code_modules.h \ 1.31 + src/processor/basic_source_line_resolver_types.h \ 1.32 + src/processor/basic_source_line_resolver.cc \ 1.33 + src/processor/binarystream.h \ 1.34 +@@ -430,16 +431,17 @@ 1.35 + src_tools_linux_dump_syms_dump_syms_SOURCES = \ 1.36 + src/common/dwarf_cfi_to_module.cc \ 1.37 + src/common/dwarf_cu_to_module.cc \ 1.38 + src/common/dwarf_line_to_module.cc \ 1.39 + src/common/language.cc \ 1.40 + src/common/module.cc \ 1.41 + src/common/stabs_reader.cc \ 1.42 + src/common/stabs_to_module.cc \ 1.43 ++ src/common/unique_string.cc \ 1.44 + src/common/dwarf/bytereader.cc \ 1.45 + src/common/dwarf/dwarf2diehandler.cc \ 1.46 + src/common/dwarf/dwarf2reader.cc \ 1.47 + src/common/linux/dump_symbols.cc \ 1.48 + src/common/linux/elf_symbols_to_module.cc \ 1.49 + src/common/linux/elfutils.cc \ 1.50 + src/common/linux/file_id.cc \ 1.51 + src/common/linux/linux_libc_support.cc \ 1.52 +@@ -473,16 +475,17 @@ 1.53 + src/common/memory_range_unittest.cc \ 1.54 + src/common/module.cc \ 1.55 + src/common/module_unittest.cc \ 1.56 + src/common/stabs_reader.cc \ 1.57 + src/common/stabs_reader_unittest.cc \ 1.58 + src/common/stabs_to_module.cc \ 1.59 + src/common/stabs_to_module_unittest.cc \ 1.60 + src/common/test_assembler.cc \ 1.61 ++ src/common/unique_string.cc \ 1.62 + src/common/dwarf/bytereader.cc \ 1.63 + src/common/dwarf/bytereader_unittest.cc \ 1.64 + src/common/dwarf/cfi_assembler.cc \ 1.65 + src/common/dwarf/dwarf2diehandler.cc \ 1.66 + src/common/dwarf/dwarf2diehandler_unittest.cc \ 1.67 + src/common/dwarf/dwarf2reader.cc \ 1.68 + src/common/dwarf/dwarf2reader_cfi_unittest.cc \ 1.69 + src/common/dwarf/dwarf2reader_die_unittest.cc \ 1.70 +@@ -561,31 +564,33 @@ 1.71 + src_processor_basic_source_line_resolver_unittest_CPPFLAGS = \ 1.72 + -I$(top_srcdir)/src \ 1.73 + -I$(top_srcdir)/src/testing/include \ 1.74 + -I$(top_srcdir)/src/testing/gtest/include \ 1.75 + -I$(top_srcdir)/src/testing/gtest \ 1.76 + -I$(top_srcdir)/src/testing 1.77 + src_processor_basic_source_line_resolver_unittest_LDADD = \ 1.78 + src/common/module.o \ 1.79 ++ src/common/unique_string.o \ 1.80 + src/processor/basic_source_line_resolver.o \ 1.81 + src/processor/cfi_frame_info.o \ 1.82 + src/processor/pathname_stripper.o \ 1.83 + src/processor/logging.o \ 1.84 + src/processor/source_line_resolver_base.o \ 1.85 + src/processor/tokenize.o \ 1.86 + $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.87 + 1.88 + src_processor_cfi_frame_info_unittest_SOURCES = \ 1.89 + src/processor/cfi_frame_info_unittest.cc \ 1.90 + src/testing/gtest/src/gtest-all.cc \ 1.91 + src/testing/gtest/src/gtest_main.cc \ 1.92 + src/testing/src/gmock-all.cc 1.93 + src_processor_cfi_frame_info_unittest_LDADD = \ 1.94 + src/common/module.o \ 1.95 ++ src/common/unique_string.o \ 1.96 + src/processor/cfi_frame_info.o \ 1.97 + src/processor/logging.o \ 1.98 + src/processor/pathname_stripper.o \ 1.99 + $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.100 + src_processor_cfi_frame_info_unittest_CPPFLAGS = \ 1.101 + -I$(top_srcdir)/src \ 1.102 + -I$(top_srcdir)/src/testing/include \ 1.103 + -I$(top_srcdir)/src/testing/gtest/include \ 1.104 +@@ -606,16 +611,17 @@ 1.105 + src_processor_exploitability_unittest_CPPFLAGS = \ 1.106 + -I$(top_srcdir)/src \ 1.107 + -I$(top_srcdir)/src/testing/include \ 1.108 + -I$(top_srcdir)/src/testing/gtest/include \ 1.109 + -I$(top_srcdir)/src/testing/gtest \ 1.110 + -I$(top_srcdir)/src/testing 1.111 + src_processor_exploitability_unittest_LDADD = \ 1.112 + src/common/module.o \ 1.113 ++ src/common/unique_string.o \ 1.114 + src/processor/minidump_processor.o \ 1.115 + src/processor/process_state.o \ 1.116 + src/processor/disassembler_x86.o \ 1.117 + src/processor/exploitability.o \ 1.118 + src/processor/exploitability_win.o \ 1.119 + src/processor/basic_code_modules.o \ 1.120 + src/processor/basic_source_line_resolver.o \ 1.121 + src/processor/call_stack.o \ 1.122 +@@ -659,16 +665,17 @@ 1.123 + src_processor_fast_source_line_resolver_unittest_CPPFLAGS = \ 1.124 + -I$(top_srcdir)/src \ 1.125 + -I$(top_srcdir)/src/testing/include \ 1.126 + -I$(top_srcdir)/src/testing/gtest/include \ 1.127 + -I$(top_srcdir)/src/testing/gtest \ 1.128 + -I$(top_srcdir)/src/testing 1.129 + src_processor_fast_source_line_resolver_unittest_LDADD = \ 1.130 + src/common/module.o \ 1.131 ++ src/common/unique_string.o \ 1.132 + src/processor/fast_source_line_resolver.o \ 1.133 + src/processor/basic_source_line_resolver.o \ 1.134 + src/processor/cfi_frame_info.o \ 1.135 + src/processor/module_comparer.o \ 1.136 + src/processor/module_serializer.o \ 1.137 + src/processor/pathname_stripper.o \ 1.138 + src/processor/logging.o \ 1.139 + src/processor/source_line_resolver_base.o \ 1.140 +@@ -697,16 +704,17 @@ 1.141 + src_processor_minidump_processor_unittest_CPPFLAGS = \ 1.142 + -I$(top_srcdir)/src \ 1.143 + -I$(top_srcdir)/src/testing/include \ 1.144 + -I$(top_srcdir)/src/testing/gtest/include \ 1.145 + -I$(top_srcdir)/src/testing/gtest \ 1.146 + -I$(top_srcdir)/src/testing 1.147 + src_processor_minidump_processor_unittest_LDADD = \ 1.148 + src/common/module.o \ 1.149 ++ src/common/unique_string.o \ 1.150 + src/processor/basic_code_modules.o \ 1.151 + src/processor/basic_source_line_resolver.o \ 1.152 + src/processor/call_stack.o \ 1.153 + src/processor/cfi_frame_info.o \ 1.154 + src/processor/disassembler_x86.o \ 1.155 + src/processor/exploitability.o \ 1.156 + src/processor/exploitability_win.o \ 1.157 + src/processor/logging.o \ 1.158 +@@ -812,16 +820,17 @@ 1.159 + src_processor_pathname_stripper_unittest_LDADD = \ 1.160 + src/processor/pathname_stripper.o \ 1.161 + $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.162 + 1.163 + src_processor_postfix_evaluator_unittest_SOURCES = \ 1.164 + src/processor/postfix_evaluator_unittest.cc 1.165 + src_processor_postfix_evaluator_unittest_LDADD = \ 1.166 + src/common/module.o \ 1.167 ++ src/common/unique_string.o \ 1.168 + src/processor/logging.o \ 1.169 + src/processor/pathname_stripper.o \ 1.170 + $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.171 + 1.172 + src_processor_range_map_unittest_SOURCES = \ 1.173 + src/processor/range_map_unittest.cc 1.174 + src_processor_range_map_unittest_LDADD = \ 1.175 + src/processor/logging.o \ 1.176 +@@ -943,16 +952,17 @@ 1.177 + src/processor/logging.o \ 1.178 + src/processor/minidump.o \ 1.179 + src/processor/pathname_stripper.o 1.180 + 1.181 + src_processor_minidump_stackwalk_SOURCES = \ 1.182 + src/processor/minidump_stackwalk.cc 1.183 + src_processor_minidump_stackwalk_LDADD = \ 1.184 + src/common/module.o \ 1.185 ++ src/common/unique_string.o \ 1.186 + src/processor/basic_code_modules.o \ 1.187 + src/processor/basic_source_line_resolver.o \ 1.188 + src/processor/binarystream.o \ 1.189 + src/processor/call_stack.o \ 1.190 + src/processor/cfi_frame_info.o \ 1.191 + src/processor/disassembler_x86.o \ 1.192 + src/processor/exploitability.o \ 1.193 + src/processor/exploitability_win.o \ 1.194 +diff --git a/Makefile.in b/Makefile.in 1.195 +--- a/Makefile.in 1.196 ++++ b/Makefile.in 1.197 +@@ -267,18 +267,19 @@ 1.198 + src/google_breakpad/processor/source_line_resolver_base.h \ 1.199 + src/google_breakpad/processor/source_line_resolver_interface.h \ 1.200 + src/google_breakpad/processor/stack_frame.h \ 1.201 + src/google_breakpad/processor/stack_frame_cpu.h \ 1.202 + src/google_breakpad/processor/stack_frame_symbolizer.h \ 1.203 + src/google_breakpad/processor/stackwalker.h \ 1.204 + src/google_breakpad/processor/symbol_supplier.h \ 1.205 + src/google_breakpad/processor/system_info.h \ 1.206 +- src/common/module.cc src/processor/address_map-inl.h \ 1.207 +- src/processor/address_map.h src/processor/basic_code_module.h \ 1.208 ++ src/common/module.cc src/common/unique_string.cc \ 1.209 ++ src/processor/address_map-inl.h src/processor/address_map.h \ 1.210 ++ src/processor/basic_code_module.h \ 1.211 + src/processor/basic_code_modules.cc \ 1.212 + src/processor/basic_code_modules.h \ 1.213 + src/processor/basic_source_line_resolver_types.h \ 1.214 + src/processor/basic_source_line_resolver.cc \ 1.215 + src/processor/binarystream.h src/processor/binarystream.cc \ 1.216 + src/processor/call_stack.cc src/processor/cfi_frame_info.cc \ 1.217 + src/processor/cfi_frame_info.h \ 1.218 + src/processor/contained_range_map-inl.h \ 1.219 +@@ -332,16 +333,17 @@ 1.220 + src/processor/static_map_iterator-inl.h \ 1.221 + src/processor/static_map_iterator.h \ 1.222 + src/processor/static_map-inl.h src/processor/static_map.h \ 1.223 + src/processor/static_range_map-inl.h \ 1.224 + src/processor/static_range_map.h src/processor/tokenize.cc \ 1.225 + src/processor/tokenize.h 1.226 + @DISABLE_PROCESSOR_FALSE@am_src_libbreakpad_a_OBJECTS = \ 1.227 + @DISABLE_PROCESSOR_FALSE@ src/common/module.$(OBJEXT) \ 1.228 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.$(OBJEXT) \ 1.229 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.$(OBJEXT) \ 1.230 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.$(OBJEXT) \ 1.231 + @DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.$(OBJEXT) \ 1.232 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.$(OBJEXT) \ 1.233 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.$(OBJEXT) \ 1.234 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.$(OBJEXT) \ 1.235 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.$(OBJEXT) \ 1.236 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.$(OBJEXT) \ 1.237 +@@ -525,17 +527,18 @@ 1.238 + src/common/dwarf_cu_to_module_unittest.cc \ 1.239 + src/common/dwarf_line_to_module.cc \ 1.240 + src/common/dwarf_line_to_module_unittest.cc \ 1.241 + src/common/language.cc src/common/memory_range_unittest.cc \ 1.242 + src/common/module.cc src/common/module_unittest.cc \ 1.243 + src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \ 1.244 + src/common/stabs_to_module.cc \ 1.245 + src/common/stabs_to_module_unittest.cc \ 1.246 +- src/common/test_assembler.cc src/common/dwarf/bytereader.cc \ 1.247 ++ src/common/test_assembler.cc src/common/unique_string.cc \ 1.248 ++ src/common/dwarf/bytereader.cc \ 1.249 + src/common/dwarf/bytereader_unittest.cc \ 1.250 + src/common/dwarf/cfi_assembler.cc \ 1.251 + src/common/dwarf/dwarf2diehandler.cc \ 1.252 + src/common/dwarf/dwarf2diehandler_unittest.cc \ 1.253 + src/common/dwarf/dwarf2reader.cc \ 1.254 + src/common/dwarf/dwarf2reader_cfi_unittest.cc \ 1.255 + src/common/dwarf/dwarf2reader_die_unittest.cc \ 1.256 + src/common/linux/dump_symbols.cc \ 1.257 +@@ -569,16 +572,17 @@ 1.258 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) \ 1.259 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module.$(OBJEXT) \ 1.260 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT) \ 1.261 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT) \ 1.262 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT) \ 1.263 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT) \ 1.264 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT) \ 1.265 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT) \ 1.266 ++@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-unique_string.$(OBJEXT) \ 1.267 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT) \ 1.268 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.$(OBJEXT) \ 1.269 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-cfi_assembler.$(OBJEXT) \ 1.270 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.$(OBJEXT) \ 1.271 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT) \ 1.272 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \ 1.273 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \ 1.274 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \ 1.275 +@@ -637,16 +641,17 @@ 1.276 + src/testing/gtest/src/gtest-all.cc \ 1.277 + src/testing/src/gmock-all.cc 1.278 + @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) \ 1.279 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_basic_source_line_resolver_unittest-gtest-all.$(OBJEXT) \ 1.280 + @DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_basic_source_line_resolver_unittest-gmock-all.$(OBJEXT) 1.281 + src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_basic_source_line_resolver_unittest_OBJECTS) 1.282 + @DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_DEPENDENCIES = \ 1.283 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.284 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.285 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.286 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.287 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.288 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.289 + @DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \ 1.290 + @DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \ 1.291 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \ 1.292 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) 1.293 +@@ -671,16 +676,17 @@ 1.294 + @DISABLE_PROCESSOR_FALSE@am_src_processor_cfi_frame_info_unittest_OBJECTS = src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.$(OBJEXT) \ 1.295 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_cfi_frame_info_unittest-gtest-all.$(OBJEXT) \ 1.296 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_cfi_frame_info_unittest-gtest_main.$(OBJEXT) \ 1.297 + @DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_cfi_frame_info_unittest-gmock-all.$(OBJEXT) 1.298 + src_processor_cfi_frame_info_unittest_OBJECTS = \ 1.299 + $(am_src_processor_cfi_frame_info_unittest_OBJECTS) 1.300 + @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_DEPENDENCIES = \ 1.301 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.302 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.303 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.304 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.305 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.306 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \ 1.307 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) 1.308 + am__src_processor_contained_range_map_unittest_SOURCES_DIST = \ 1.309 + src/processor/contained_range_map_unittest.cc 1.310 + @DISABLE_PROCESSOR_FALSE@am_src_processor_contained_range_map_unittest_OBJECTS = src/processor/contained_range_map_unittest.$(OBJEXT) 1.311 +@@ -713,16 +719,17 @@ 1.312 + @DISABLE_PROCESSOR_FALSE@am_src_processor_exploitability_unittest_OBJECTS = src/processor/src_processor_exploitability_unittest-exploitability_unittest.$(OBJEXT) \ 1.313 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_exploitability_unittest-gtest-all.$(OBJEXT) \ 1.314 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_exploitability_unittest-gtest_main.$(OBJEXT) \ 1.315 + @DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_exploitability_unittest-gmock-all.$(OBJEXT) 1.316 + src_processor_exploitability_unittest_OBJECTS = \ 1.317 + $(am_src_processor_exploitability_unittest_OBJECTS) 1.318 + @DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_DEPENDENCIES = \ 1.319 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.320 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.321 + @DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \ 1.322 + @DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \ 1.323 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \ 1.324 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \ 1.325 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \ 1.326 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \ 1.327 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.328 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \ 1.329 +@@ -748,16 +755,17 @@ 1.330 + src/testing/gtest/src/gtest-all.cc \ 1.331 + src/testing/src/gmock-all.cc 1.332 + @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) \ 1.333 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.$(OBJEXT) \ 1.334 + @DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.$(OBJEXT) 1.335 + src_processor_fast_source_line_resolver_unittest_OBJECTS = $(am_src_processor_fast_source_line_resolver_unittest_OBJECTS) 1.336 + @DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_DEPENDENCIES = \ 1.337 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.338 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.339 + @DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.o \ 1.340 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.341 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.342 + @DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \ 1.343 + @DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \ 1.344 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.345 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.346 + @DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \ 1.347 +@@ -794,16 +802,17 @@ 1.348 + src/testing/src/gmock-all.cc 1.349 + @DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_processor_unittest_OBJECTS = src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT) \ 1.350 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT) \ 1.351 + @DISABLE_PROCESSOR_FALSE@ src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT) 1.352 + src_processor_minidump_processor_unittest_OBJECTS = \ 1.353 + $(am_src_processor_minidump_processor_unittest_OBJECTS) 1.354 + @DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_DEPENDENCIES = \ 1.355 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.356 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.357 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \ 1.358 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.359 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \ 1.360 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.361 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \ 1.362 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \ 1.363 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \ 1.364 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.365 +@@ -826,16 +835,17 @@ 1.366 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) 1.367 + am__src_processor_minidump_stackwalk_SOURCES_DIST = \ 1.368 + src/processor/minidump_stackwalk.cc 1.369 + @DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_stackwalk_OBJECTS = src/processor/minidump_stackwalk.$(OBJEXT) 1.370 + src_processor_minidump_stackwalk_OBJECTS = \ 1.371 + $(am_src_processor_minidump_stackwalk_OBJECTS) 1.372 + @DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_DEPENDENCIES = \ 1.373 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.374 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.375 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \ 1.376 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.377 + @DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \ 1.378 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \ 1.379 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.380 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \ 1.381 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \ 1.382 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \ 1.383 +@@ -889,16 +899,17 @@ 1.384 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) 1.385 + am__src_processor_postfix_evaluator_unittest_SOURCES_DIST = \ 1.386 + src/processor/postfix_evaluator_unittest.cc 1.387 + @DISABLE_PROCESSOR_FALSE@am_src_processor_postfix_evaluator_unittest_OBJECTS = src/processor/postfix_evaluator_unittest.$(OBJEXT) 1.388 + src_processor_postfix_evaluator_unittest_OBJECTS = \ 1.389 + $(am_src_processor_postfix_evaluator_unittest_OBJECTS) 1.390 + @DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_DEPENDENCIES = \ 1.391 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.392 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.393 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.394 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.395 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \ 1.396 + @DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) 1.397 + am__src_processor_range_map_unittest_SOURCES_DIST = \ 1.398 + src/processor/range_map_unittest.cc 1.399 + @DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_unittest_OBJECTS = src/processor/range_map_unittest.$(OBJEXT) 1.400 + src_processor_range_map_unittest_OBJECTS = \ 1.401 +@@ -1069,33 +1080,35 @@ 1.402 + src_tools_linux_core2md_core2md_OBJECTS = \ 1.403 + $(am_src_tools_linux_core2md_core2md_OBJECTS) 1.404 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_DEPENDENCIES = src/client/linux/libbreakpad_client.a 1.405 + am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \ 1.406 + src/common/dwarf_cfi_to_module.cc \ 1.407 + src/common/dwarf_cu_to_module.cc \ 1.408 + src/common/dwarf_line_to_module.cc src/common/language.cc \ 1.409 + src/common/module.cc src/common/stabs_reader.cc \ 1.410 +- src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \ 1.411 ++ src/common/stabs_to_module.cc src/common/unique_string.cc \ 1.412 ++ src/common/dwarf/bytereader.cc \ 1.413 + src/common/dwarf/dwarf2diehandler.cc \ 1.414 + src/common/dwarf/dwarf2reader.cc \ 1.415 + src/common/linux/dump_symbols.cc \ 1.416 + src/common/linux/elf_symbols_to_module.cc \ 1.417 + src/common/linux/elfutils.cc src/common/linux/file_id.cc \ 1.418 + src/common/linux/linux_libc_support.cc \ 1.419 + src/common/linux/memory_mapped_file.cc \ 1.420 + src/common/linux/safe_readlink.cc \ 1.421 + src/tools/linux/dump_syms/dump_syms.cc 1.422 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_dump_syms_dump_syms_OBJECTS = src/common/dwarf_cfi_to_module.$(OBJEXT) \ 1.423 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.$(OBJEXT) \ 1.424 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.$(OBJEXT) \ 1.425 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.$(OBJEXT) \ 1.426 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.$(OBJEXT) \ 1.427 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.$(OBJEXT) \ 1.428 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.$(OBJEXT) \ 1.429 ++@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/unique_string.$(OBJEXT) \ 1.430 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.$(OBJEXT) \ 1.431 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.$(OBJEXT) \ 1.432 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.$(OBJEXT) \ 1.433 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.$(OBJEXT) \ 1.434 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \ 1.435 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.$(OBJEXT) \ 1.436 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.$(OBJEXT) \ 1.437 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.$(OBJEXT) \ 1.438 +@@ -1416,16 +1429,17 @@ 1.439 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_interface.h \ 1.440 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame.h \ 1.441 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_cpu.h \ 1.442 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_symbolizer.h \ 1.443 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stackwalker.h \ 1.444 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/symbol_supplier.h \ 1.445 + @DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/system_info.h \ 1.446 + @DISABLE_PROCESSOR_FALSE@ src/common/module.cc \ 1.447 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.cc \ 1.448 + @DISABLE_PROCESSOR_FALSE@ src/processor/address_map-inl.h \ 1.449 + @DISABLE_PROCESSOR_FALSE@ src/processor/address_map.h \ 1.450 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_module.h \ 1.451 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.cc \ 1.452 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.h \ 1.453 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_types.h \ 1.454 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.cc \ 1.455 + @DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.h \ 1.456 +@@ -1618,16 +1632,17 @@ 1.457 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_dump_syms_dump_syms_SOURCES = \ 1.458 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \ 1.459 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \ 1.460 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \ 1.461 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \ 1.462 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \ 1.463 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \ 1.464 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \ 1.465 ++@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/unique_string.cc \ 1.466 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \ 1.467 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \ 1.468 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \ 1.469 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \ 1.470 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \ 1.471 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \ 1.472 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \ 1.473 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \ 1.474 +@@ -1661,16 +1676,17 @@ 1.475 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \ 1.476 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \ 1.477 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module_unittest.cc \ 1.478 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \ 1.479 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader_unittest.cc \ 1.480 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \ 1.481 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module_unittest.cc \ 1.482 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/test_assembler.cc \ 1.483 ++@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/unique_string.cc \ 1.484 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \ 1.485 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader_unittest.cc \ 1.486 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \ 1.487 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \ 1.488 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler_unittest.cc \ 1.489 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \ 1.490 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ 1.491 + @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \ 1.492 +@@ -1753,32 +1769,34 @@ 1.493 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \ 1.494 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \ 1.495 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \ 1.496 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \ 1.497 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing 1.498 + 1.499 + @DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_LDADD = \ 1.500 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.501 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.502 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.503 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.504 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.505 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.506 + @DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \ 1.507 + @DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \ 1.508 + @DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.509 + 1.510 + @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \ 1.511 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info_unittest.cc \ 1.512 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/gtest-all.cc \ 1.513 + @DISABLE_PROCESSOR_FALSE@ src/testing/gtest/src/gtest_main.cc \ 1.514 + @DISABLE_PROCESSOR_FALSE@ src/testing/src/gmock-all.cc 1.515 + 1.516 + @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_LDADD = \ 1.517 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.518 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.519 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.520 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.521 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.522 + @DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.523 + 1.524 + @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_CPPFLAGS = \ 1.525 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \ 1.526 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \ 1.527 +@@ -1803,16 +1821,17 @@ 1.528 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \ 1.529 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \ 1.530 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \ 1.531 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \ 1.532 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing 1.533 + 1.534 + @DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_LDADD = \ 1.535 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.536 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.537 + @DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \ 1.538 + @DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \ 1.539 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \ 1.540 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \ 1.541 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \ 1.542 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \ 1.543 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.544 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \ 1.545 +@@ -1860,16 +1879,17 @@ 1.546 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \ 1.547 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \ 1.548 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \ 1.549 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \ 1.550 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing 1.551 + 1.552 + @DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_LDADD = \ 1.553 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.554 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.555 + @DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.o \ 1.556 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.557 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.558 + @DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \ 1.559 + @DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \ 1.560 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.561 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.562 + @DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \ 1.563 +@@ -1902,16 +1922,17 @@ 1.564 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src \ 1.565 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/include \ 1.566 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \ 1.567 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing/gtest \ 1.568 + @DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing 1.569 + 1.570 + @DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_LDADD = \ 1.571 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.572 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.573 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \ 1.574 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.575 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \ 1.576 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.577 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \ 1.578 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \ 1.579 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \ 1.580 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.581 +@@ -2029,16 +2050,17 @@ 1.582 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.583 + @DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.584 + 1.585 + @DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_SOURCES = \ 1.586 + @DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest.cc 1.587 + 1.588 + @DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_LDADD = \ 1.589 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.590 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.591 + @DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \ 1.592 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \ 1.593 + @DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) 1.594 + 1.595 + @DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_SOURCES = \ 1.596 + @DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest.cc 1.597 + 1.598 + @DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_LDADD = \ 1.599 +@@ -2169,16 +2191,17 @@ 1.600 + @DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \ 1.601 + @DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o 1.602 + 1.603 + @DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_SOURCES = \ 1.604 + @DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk.cc 1.605 + 1.606 + @DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_LDADD = \ 1.607 + @DISABLE_PROCESSOR_FALSE@ src/common/module.o \ 1.608 ++@DISABLE_PROCESSOR_FALSE@ src/common/unique_string.o \ 1.609 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \ 1.610 + @DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \ 1.611 + @DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \ 1.612 + @DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \ 1.613 + @DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \ 1.614 + @DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \ 1.615 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \ 1.616 + @DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \ 1.617 +@@ -2527,16 +2550,18 @@ 1.618 + @$(MKDIR_P) src/client/linux 1.619 + @: > src/client/linux/$(am__dirstamp) 1.620 + 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) 1.621 + -rm -f src/client/linux/libbreakpad_client.a 1.622 + $(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) 1.623 + $(RANLIB) src/client/linux/libbreakpad_client.a 1.624 + src/common/module.$(OBJEXT): src/common/$(am__dirstamp) \ 1.625 + src/common/$(DEPDIR)/$(am__dirstamp) 1.626 ++src/common/unique_string.$(OBJEXT): src/common/$(am__dirstamp) \ 1.627 ++ src/common/$(DEPDIR)/$(am__dirstamp) 1.628 + src/processor/$(am__dirstamp): 1.629 + @$(MKDIR_P) src/processor 1.630 + @: > src/processor/$(am__dirstamp) 1.631 + src/processor/$(DEPDIR)/$(am__dirstamp): 1.632 + @$(MKDIR_P) src/processor/$(DEPDIR) 1.633 + @: > src/processor/$(DEPDIR)/$(am__dirstamp) 1.634 + src/processor/basic_code_modules.$(OBJEXT): \ 1.635 + src/processor/$(am__dirstamp) \ 1.636 +@@ -2863,16 +2888,19 @@ 1.637 + src/common/$(am__dirstamp) \ 1.638 + src/common/$(DEPDIR)/$(am__dirstamp) 1.639 + src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT): \ 1.640 + src/common/$(am__dirstamp) \ 1.641 + src/common/$(DEPDIR)/$(am__dirstamp) 1.642 + src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT): \ 1.643 + src/common/$(am__dirstamp) \ 1.644 + src/common/$(DEPDIR)/$(am__dirstamp) 1.645 ++src/common/src_common_dumper_unittest-unique_string.$(OBJEXT): \ 1.646 ++ src/common/$(am__dirstamp) \ 1.647 ++ src/common/$(DEPDIR)/$(am__dirstamp) 1.648 + src/common/dwarf/$(am__dirstamp): 1.649 + @$(MKDIR_P) src/common/dwarf 1.650 + @: > src/common/dwarf/$(am__dirstamp) 1.651 + src/common/dwarf/$(DEPDIR)/$(am__dirstamp): 1.652 + @$(MKDIR_P) src/common/dwarf/$(DEPDIR) 1.653 + @: > src/common/dwarf/$(DEPDIR)/$(am__dirstamp) 1.654 + src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT): \ 1.655 + src/common/dwarf/$(am__dirstamp) \ 1.656 +@@ -3470,28 +3498,30 @@ 1.657 + -rm -f src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) 1.658 + -rm -f src/common/src_common_dumper_unittest-module.$(OBJEXT) 1.659 + -rm -f src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT) 1.660 + -rm -f src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT) 1.661 + -rm -f src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT) 1.662 + -rm -f src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT) 1.663 + -rm -f src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT) 1.664 + -rm -f src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT) 1.665 ++ -rm -f src/common/src_common_dumper_unittest-unique_string.$(OBJEXT) 1.666 + -rm -f src/common/src_common_test_assembler_unittest-test_assembler.$(OBJEXT) 1.667 + -rm -f src/common/src_common_test_assembler_unittest-test_assembler_unittest.$(OBJEXT) 1.668 + -rm -f src/common/src_processor_minidump_unittest-test_assembler.$(OBJEXT) 1.669 + -rm -f src/common/src_processor_stackwalker_amd64_unittest-test_assembler.$(OBJEXT) 1.670 + -rm -f src/common/src_processor_stackwalker_arm_unittest-test_assembler.$(OBJEXT) 1.671 + -rm -f src/common/src_processor_stackwalker_x86_unittest-test_assembler.$(OBJEXT) 1.672 + -rm -f src/common/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT) 1.673 + -rm -f src/common/stabs_reader.$(OBJEXT) 1.674 + -rm -f src/common/stabs_to_module.$(OBJEXT) 1.675 + -rm -f src/common/string_conversion.$(OBJEXT) 1.676 + -rm -f src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.$(OBJEXT) 1.677 + -rm -f src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT) 1.678 ++ -rm -f src/common/unique_string.$(OBJEXT) 1.679 + -rm -f src/processor/address_map_unittest.$(OBJEXT) 1.680 + -rm -f src/processor/basic_code_modules.$(OBJEXT) 1.681 + -rm -f src/processor/basic_source_line_resolver.$(OBJEXT) 1.682 + -rm -f src/processor/binarystream.$(OBJEXT) 1.683 + -rm -f src/processor/call_stack.$(OBJEXT) 1.684 + -rm -f src/processor/cfi_frame_info.$(OBJEXT) 1.685 + -rm -f src/processor/contained_range_map_unittest.$(OBJEXT) 1.686 + -rm -f src/processor/disassembler_x86.$(OBJEXT) 1.687 +@@ -3663,26 +3693,28 @@ 1.688 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po@am__quote@ 1.689 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po@am__quote@ 1.690 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po@am__quote@ 1.691 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po@am__quote@ 1.692 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Po@am__quote@ 1.693 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Po@am__quote@ 1.694 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Po@am__quote@ 1.695 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po@am__quote@ 1.696 ++@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Po@am__quote@ 1.697 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Po@am__quote@ 1.698 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Po@am__quote@ 1.699 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po@am__quote@ 1.700 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Po@am__quote@ 1.701 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Po@am__quote@ 1.702 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Po@am__quote@ 1.703 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po@am__quote@ 1.704 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_reader.Po@am__quote@ 1.705 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_to_module.Po@am__quote@ 1.706 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/string_conversion.Po@am__quote@ 1.707 ++@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/unique_string.Po@am__quote@ 1.708 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/breakpad_getcontext.Po@am__quote@ 1.709 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Po@am__quote@ 1.710 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po@am__quote@ 1.711 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/bytereader.Po@am__quote@ 1.712 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2diehandler.Po@am__quote@ 1.713 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2reader.Po@am__quote@ 1.714 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po@am__quote@ 1.715 + @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po@am__quote@ 1.716 +@@ -4474,16 +4506,30 @@ 1.717 + 1.718 + src/common/src_common_dumper_unittest-test_assembler.obj: src/common/test_assembler.cc 1.719 + @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` 1.720 + @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 1.721 + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/test_assembler.cc' object='src/common/src_common_dumper_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@ 1.722 + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1.723 + @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` 1.724 + 1.725 ++src/common/src_common_dumper_unittest-unique_string.o: src/common/unique_string.cc 1.726 ++@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 1.727 ++@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 1.728 ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/unique_string.cc' object='src/common/src_common_dumper_unittest-unique_string.o' libtool=no @AMDEPBACKSLASH@ 1.729 ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1.730 ++@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 1.731 ++ 1.732 ++src/common/src_common_dumper_unittest-unique_string.obj: src/common/unique_string.cc 1.733 ++@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` 1.734 ++@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 1.735 ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/unique_string.cc' object='src/common/src_common_dumper_unittest-unique_string.obj' libtool=no @AMDEPBACKSLASH@ 1.736 ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1.737 ++@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` 1.738 ++ 1.739 + src/common/dwarf/src_common_dumper_unittest-bytereader.o: src/common/dwarf/bytereader.cc 1.740 + @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 1.741 + @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 1.742 + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader.o' libtool=no @AMDEPBACKSLASH@ 1.743 + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1.744 + @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 1.745 + 1.746 + src/common/dwarf/src_common_dumper_unittest-bytereader.obj: src/common/dwarf/bytereader.cc 1.747 +diff --git a/src/common/dwarf_cfi_to_module.cc b/src/common/dwarf_cfi_to_module.cc 1.748 +--- a/src/common/dwarf_cfi_to_module.cc 1.749 ++++ b/src/common/dwarf_cfi_to_module.cc 1.750 +@@ -37,40 +37,44 @@ 1.751 + #include <sstream> 1.752 + 1.753 + #include "common/dwarf_cfi_to_module.h" 1.754 + 1.755 + namespace google_breakpad { 1.756 + 1.757 + using std::ostringstream; 1.758 + 1.759 +-vector<string> DwarfCFIToModule::RegisterNames::MakeVector( 1.760 +- const char * const *strings, 1.761 ++vector<const UniqueString*> DwarfCFIToModule::RegisterNames::MakeVector( 1.762 ++ const char* const* strings, 1.763 + size_t size) { 1.764 +- vector<string> names(strings, strings + size); 1.765 ++ vector<const UniqueString*> names(size, NULL); 1.766 ++ for (size_t i = 0; i < size; ++i) { 1.767 ++ names[i] = ToUniqueString(strings[i]); 1.768 ++ } 1.769 ++ 1.770 + return names; 1.771 + } 1.772 + 1.773 +-vector<string> DwarfCFIToModule::RegisterNames::I386() { 1.774 ++vector<const UniqueString*> DwarfCFIToModule::RegisterNames::I386() { 1.775 + static const char *const names[] = { 1.776 + "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi", 1.777 + "$eip", "$eflags", "$unused1", 1.778 + "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", 1.779 + "$unused2", "$unused3", 1.780 + "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", 1.781 + "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", 1.782 + "$fcw", "$fsw", "$mxcsr", 1.783 + "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5", 1.784 + "$tr", "$ldtr" 1.785 + }; 1.786 + 1.787 + return MakeVector(names, sizeof(names) / sizeof(names[0])); 1.788 + } 1.789 + 1.790 +-vector<string> DwarfCFIToModule::RegisterNames::X86_64() { 1.791 ++vector<const UniqueString*> DwarfCFIToModule::RegisterNames::X86_64() { 1.792 + static const char *const names[] = { 1.793 + "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp", 1.794 + "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", 1.795 + "$rip", 1.796 + "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", 1.797 + "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15", 1.798 + "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", 1.799 + "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", 1.800 +@@ -80,17 +84,17 @@ 1.801 + "$tr", "$ldtr", 1.802 + "$mxcsr", "$fcw", "$fsw" 1.803 + }; 1.804 + 1.805 + return MakeVector(names, sizeof(names) / sizeof(names[0])); 1.806 + } 1.807 + 1.808 + // Per ARM IHI 0040A, section 3.1 1.809 +-vector<string> DwarfCFIToModule::RegisterNames::ARM() { 1.810 ++vector<const UniqueString*> DwarfCFIToModule::RegisterNames::ARM() { 1.811 + static const char *const names[] = { 1.812 + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1.813 + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", 1.814 + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 1.815 + "fps", "cpsr", "", "", "", "", "", "", 1.816 + "", "", "", "", "", "", "", "", 1.817 + "", "", "", "", "", "", "", "", 1.818 + "", "", "", "", "", "", "", "", 1.819 +@@ -122,40 +126,40 @@ 1.820 + return_address_ = return_address; 1.821 + 1.822 + // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI 1.823 + // may not establish any rule for .ra if the return address column 1.824 + // is an ordinary register, and that register holds the return 1.825 + // address on entry to the function. So establish an initial .ra 1.826 + // rule citing the return address register. 1.827 + if (return_address_ < register_names_.size()) 1.828 +- entry_->initial_rules[ra_name_] 1.829 ++ entry_->initial_rules[ustr__ZDra()] 1.830 + = Module::Expr(register_names_[return_address_], 0, false); 1.831 + 1.832 + return true; 1.833 + } 1.834 + 1.835 +-string DwarfCFIToModule::RegisterName(int i) { 1.836 ++const UniqueString* DwarfCFIToModule::RegisterName(int i) { 1.837 + assert(entry_); 1.838 + if (i < 0) { 1.839 + assert(i == kCFARegister); 1.840 +- return cfa_name_; 1.841 ++ return ustr__ZDcfa(); 1.842 + } 1.843 + unsigned reg = i; 1.844 + if (reg == return_address_) 1.845 +- return ra_name_; 1.846 ++ return ustr__ZDra(); 1.847 + 1.848 + // Ensure that a non-empty name exists for this register value. 1.849 +- if (reg < register_names_.size() && !register_names_[reg].empty()) 1.850 ++ if (reg < register_names_.size() && register_names_[reg] != ustr__empty()) 1.851 + return register_names_[reg]; 1.852 + 1.853 + reporter_->UnnamedRegister(entry_offset_, reg); 1.854 + char buf[30]; 1.855 + sprintf(buf, "unnamed_register%u", reg); 1.856 +- return buf; 1.857 ++ return ToUniqueString(buf); 1.858 + } 1.859 + 1.860 + void DwarfCFIToModule::Record(Module::Address address, int reg, 1.861 + const Module::Expr &rule) { 1.862 + assert(entry_); 1.863 + 1.864 + // Is this one of this entry's initial rules? 1.865 + if (address == entry_->address) 1.866 +@@ -228,28 +232,30 @@ 1.867 + 1.868 + void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) { 1.869 + fprintf(stderr, "%s, section '%s': " 1.870 + "the call frame entry at offset 0x%zx refers to register %d," 1.871 + " whose name we don't know\n", 1.872 + file_.c_str(), section_.c_str(), offset, reg); 1.873 + } 1.874 + 1.875 +-void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset, 1.876 +- const string ®) { 1.877 ++void DwarfCFIToModule::Reporter::UndefinedNotSupported( 1.878 ++ size_t offset, 1.879 ++ const UniqueString* reg) { 1.880 + fprintf(stderr, "%s, section '%s': " 1.881 + "the call frame entry at offset 0x%zx sets the rule for " 1.882 + "register '%s' to 'undefined', but the Breakpad symbol file format" 1.883 + " cannot express this\n", 1.884 +- file_.c_str(), section_.c_str(), offset, reg.c_str()); 1.885 ++ file_.c_str(), section_.c_str(), offset, FromUniqueString(reg)); 1.886 + } 1.887 + 1.888 +-void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset, 1.889 +- const string ®) { 1.890 ++void DwarfCFIToModule::Reporter::ExpressionsNotSupported( 1.891 ++ size_t offset, 1.892 ++ const UniqueString* reg) { 1.893 + fprintf(stderr, "%s, section '%s': " 1.894 + "the call frame entry at offset 0x%zx uses a DWARF expression to" 1.895 + " describe how to recover register '%s', " 1.896 + " but this translator cannot yet translate DWARF expressions to" 1.897 + " Breakpad postfix expressions\n", 1.898 +- file_.c_str(), section_.c_str(), offset, reg.c_str()); 1.899 ++ file_.c_str(), section_.c_str(), offset, FromUniqueString(reg)); 1.900 + } 1.901 + 1.902 + } // namespace google_breakpad 1.903 +diff --git a/src/common/dwarf_cfi_to_module.h b/src/common/dwarf_cfi_to_module.h 1.904 +--- a/src/common/dwarf_cfi_to_module.h 1.905 ++++ b/src/common/dwarf_cfi_to_module.h 1.906 +@@ -44,16 +44,17 @@ 1.907 + 1.908 + #include <set> 1.909 + #include <string> 1.910 + #include <vector> 1.911 + 1.912 + #include "common/module.h" 1.913 + #include "common/dwarf/dwarf2reader.h" 1.914 + #include "common/using_std_string.h" 1.915 ++#include "common/unique_string.h" 1.916 + 1.917 + namespace google_breakpad { 1.918 + 1.919 + using dwarf2reader::CallFrameInfo; 1.920 + using google_breakpad::Module; 1.921 + using std::set; 1.922 + using std::vector; 1.923 + 1.924 +@@ -78,61 +79,65 @@ 1.925 + // The DWARF CFI entry at OFFSET cites register REG, but REG is not 1.926 + // covered by the vector of register names passed to the 1.927 + // DwarfCFIToModule constructor, nor does it match the return 1.928 + // address column number for this entry. 1.929 + virtual void UnnamedRegister(size_t offset, int reg); 1.930 + 1.931 + // The DWARF CFI entry at OFFSET says that REG is undefined, but the 1.932 + // Breakpad symbol file format cannot express this. 1.933 +- virtual void UndefinedNotSupported(size_t offset, const string ®); 1.934 ++ virtual void UndefinedNotSupported(size_t offset, 1.935 ++ const UniqueString* reg); 1.936 + 1.937 + // The DWARF CFI entry at OFFSET says that REG uses a DWARF 1.938 + // expression to find its value, but DwarfCFIToModule is not 1.939 + // capable of translating DWARF expressions to Breakpad postfix 1.940 + // expressions. 1.941 +- virtual void ExpressionsNotSupported(size_t offset, const string ®); 1.942 ++ virtual void ExpressionsNotSupported(size_t offset, 1.943 ++ const UniqueString* reg); 1.944 + 1.945 + protected: 1.946 + string file_, section_; 1.947 + }; 1.948 + 1.949 + // Register name tables. If TABLE is a vector returned by one of these 1.950 + // functions, then TABLE[R] is the name of the register numbered R in 1.951 + // DWARF call frame information. 1.952 + class RegisterNames { 1.953 + public: 1.954 + // Intel's "x86" or IA-32. 1.955 +- static vector<string> I386(); 1.956 ++ static vector<const UniqueString*> I386(); 1.957 + 1.958 + // AMD x86_64, AMD64, Intel EM64T, or Intel 64 1.959 +- static vector<string> X86_64(); 1.960 ++ static vector<const UniqueString*> X86_64(); 1.961 + 1.962 + // ARM. 1.963 +- static vector<string> ARM(); 1.964 ++ static vector<const UniqueString*> ARM(); 1.965 + 1.966 + private: 1.967 + // Given STRINGS, an array of C strings with SIZE elements, return an 1.968 + // equivalent vector<string>. 1.969 +- static vector<string> MakeVector(const char * const *strings, size_t size); 1.970 ++ static vector<const UniqueString*> MakeVector(const char * const *strings, 1.971 ++ size_t size); 1.972 + }; 1.973 + 1.974 + // Create a handler for the dwarf2reader::CallFrameInfo parser that 1.975 + // records the stack unwinding information it receives in MODULE. 1.976 + // 1.977 + // Use REGISTER_NAMES[I] as the name of register number I; *this 1.978 + // keeps a reference to the vector, so the vector should remain 1.979 + // alive for as long as the DwarfCFIToModule does. 1.980 + // 1.981 + // Use REPORTER for reporting problems encountered in the conversion 1.982 + // process. 1.983 +- DwarfCFIToModule(Module *module, const vector<string> ®ister_names, 1.984 ++ DwarfCFIToModule(Module *module, 1.985 ++ const vector<const UniqueString*> ®ister_names, 1.986 + Reporter *reporter) 1.987 + : module_(module), register_names_(register_names), reporter_(reporter), 1.988 +- entry_(NULL), return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") { 1.989 ++ entry_(NULL), return_address_(-1) { 1.990 + } 1.991 + virtual ~DwarfCFIToModule() { delete entry_; } 1.992 + 1.993 + virtual bool Entry(size_t offset, uint64 address, uint64 length, 1.994 + uint8 version, const string &augmentation, 1.995 + unsigned return_address); 1.996 + virtual bool UndefinedRule(uint64 address, int reg); 1.997 + virtual bool SameValueRule(uint64 address, int reg); 1.998 +@@ -144,53 +149,36 @@ 1.999 + virtual bool ExpressionRule(uint64 address, int reg, 1.1000 + const string &expression); 1.1001 + virtual bool ValExpressionRule(uint64 address, int reg, 1.1002 + const string &expression); 1.1003 + virtual bool End(); 1.1004 + 1.1005 + private: 1.1006 + // Return the name to use for register REG. 1.1007 +- string RegisterName(int i); 1.1008 ++ const UniqueString* RegisterName(int i); 1.1009 + 1.1010 + // Record RULE for register REG at ADDRESS. 1.1011 + void Record(Module::Address address, int reg, const Module::Expr &rule); 1.1012 + 1.1013 + // The module to which we should add entries. 1.1014 + Module *module_; 1.1015 + 1.1016 + // Map from register numbers to register names. 1.1017 +- const vector<string> ®ister_names_; 1.1018 ++ const vector<const UniqueString*> ®ister_names_; 1.1019 + 1.1020 + // The reporter to use to report problems. 1.1021 + Reporter *reporter_; 1.1022 + 1.1023 + // The current entry we're constructing. 1.1024 + Module::StackFrameEntry *entry_; 1.1025 + 1.1026 + // The section offset of the current frame description entry, for 1.1027 + // use in error messages. 1.1028 + size_t entry_offset_; 1.1029 + 1.1030 + // The return address column for that entry. 1.1031 + unsigned return_address_; 1.1032 +- 1.1033 +- // The names of the return address and canonical frame address. Putting 1.1034 +- // these here instead of using string literals allows us to share their 1.1035 +- // texts in reference-counted std::string implementations (all the 1.1036 +- // popular ones). Many, many rules cite these strings. 1.1037 +- string cfa_name_, ra_name_; 1.1038 +- 1.1039 +- // A set of strings used by this CFI. Before storing a string in one of 1.1040 +- // our data structures, insert it into this set, and then use the string 1.1041 +- // from the set. 1.1042 +- // 1.1043 +- // Because std::string uses reference counting internally, simply using 1.1044 +- // strings from this set, even if passed by value, assigned, or held 1.1045 +- // directly in structures and containers (map<string, ...>, for example), 1.1046 +- // causes those strings to share a single instance of each distinct piece 1.1047 +- // of text. 1.1048 +- set<string> common_strings_; 1.1049 + }; 1.1050 + 1.1051 + } // namespace google_breakpad 1.1052 + 1.1053 + #endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H 1.1054 +diff --git a/src/common/dwarf_cfi_to_module_unittest.cc b/src/common/dwarf_cfi_to_module_unittest.cc 1.1055 +--- a/src/common/dwarf_cfi_to_module_unittest.cc 1.1056 ++++ b/src/common/dwarf_cfi_to_module_unittest.cc 1.1057 +@@ -37,52 +37,59 @@ 1.1058 + #include "breakpad_googletest_includes.h" 1.1059 + #include "common/dwarf_cfi_to_module.h" 1.1060 + #include "common/using_std_string.h" 1.1061 + 1.1062 + using std::vector; 1.1063 + 1.1064 + using google_breakpad::Module; 1.1065 + using google_breakpad::DwarfCFIToModule; 1.1066 ++using google_breakpad::ToUniqueString; 1.1067 ++using google_breakpad::UniqueString; 1.1068 ++using google_breakpad::ustr__ZDcfa; 1.1069 ++using google_breakpad::ustr__ZDra; 1.1070 ++using google_breakpad::ustr__empty; 1.1071 + using testing::ContainerEq; 1.1072 + using testing::Test; 1.1073 + using testing::_; 1.1074 + 1.1075 + struct MockCFIReporter: public DwarfCFIToModule::Reporter { 1.1076 + MockCFIReporter(const string &file, const string §ion) 1.1077 + : Reporter(file, section) { } 1.1078 + MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg)); 1.1079 +- MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string ®)); 1.1080 +- MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string ®)); 1.1081 ++ MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, 1.1082 ++ const UniqueString* reg)); 1.1083 ++ MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, 1.1084 ++ const UniqueString* reg)); 1.1085 + }; 1.1086 + 1.1087 + struct DwarfCFIToModuleFixture { 1.1088 + DwarfCFIToModuleFixture() 1.1089 + : module("module name", "module os", "module arch", "module id"), 1.1090 + reporter("reporter file", "reporter section"), 1.1091 + handler(&module, register_names, &reporter) { 1.1092 +- register_names.push_back("reg0"); 1.1093 +- register_names.push_back("reg1"); 1.1094 +- register_names.push_back("reg2"); 1.1095 +- register_names.push_back("reg3"); 1.1096 +- register_names.push_back("reg4"); 1.1097 +- register_names.push_back("reg5"); 1.1098 +- register_names.push_back("reg6"); 1.1099 +- register_names.push_back("reg7"); 1.1100 +- register_names.push_back("sp"); 1.1101 +- register_names.push_back("pc"); 1.1102 +- register_names.push_back(""); 1.1103 ++ register_names.push_back(ToUniqueString("reg0")); 1.1104 ++ register_names.push_back(ToUniqueString("reg1")); 1.1105 ++ register_names.push_back(ToUniqueString("reg2")); 1.1106 ++ register_names.push_back(ToUniqueString("reg3")); 1.1107 ++ register_names.push_back(ToUniqueString("reg4")); 1.1108 ++ register_names.push_back(ToUniqueString("reg5")); 1.1109 ++ register_names.push_back(ToUniqueString("reg6")); 1.1110 ++ register_names.push_back(ToUniqueString("reg7")); 1.1111 ++ register_names.push_back(ToUniqueString("sp")); 1.1112 ++ register_names.push_back(ToUniqueString("pc")); 1.1113 ++ register_names.push_back(ustr__empty()); 1.1114 + 1.1115 + EXPECT_CALL(reporter, UnnamedRegister(_, _)).Times(0); 1.1116 + EXPECT_CALL(reporter, UndefinedNotSupported(_, _)).Times(0); 1.1117 + EXPECT_CALL(reporter, ExpressionsNotSupported(_, _)).Times(0); 1.1118 + } 1.1119 + 1.1120 + Module module; 1.1121 +- vector<string> register_names; 1.1122 ++ vector<const UniqueString*> register_names; 1.1123 + MockCFIReporter reporter; 1.1124 + DwarfCFIToModule handler; 1.1125 + vector<Module::StackFrameEntry *> entries; 1.1126 + }; 1.1127 + 1.1128 + class Entry: public DwarfCFIToModuleFixture, public Test { }; 1.1129 + 1.1130 + TEST_F(Entry, Accept) { 1.1131 +@@ -127,183 +134,190 @@ 1.1132 + } 1.1133 + uint64 entry_address, entry_size; 1.1134 + unsigned return_reg; 1.1135 + }; 1.1136 + 1.1137 + class Rule: public RuleFixture, public Test { }; 1.1138 + 1.1139 + TEST_F(Rule, UndefinedRule) { 1.1140 +- EXPECT_CALL(reporter, UndefinedNotSupported(_, "reg7")); 1.1141 ++ EXPECT_CALL(reporter, UndefinedNotSupported(_, ToUniqueString("reg7"))); 1.1142 + StartEntry(); 1.1143 + ASSERT_TRUE(handler.UndefinedRule(entry_address, 7)); 1.1144 + ASSERT_TRUE(handler.End()); 1.1145 + CheckEntry(); 1.1146 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1147 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1148 + } 1.1149 + 1.1150 + TEST_F(Rule, RegisterWithEmptyName) { 1.1151 + EXPECT_CALL(reporter, UnnamedRegister(_, 10)); 1.1152 +- EXPECT_CALL(reporter, UndefinedNotSupported(_, "unnamed_register10")); 1.1153 ++ EXPECT_CALL(reporter, 1.1154 ++ UndefinedNotSupported(_, ToUniqueString("unnamed_register10"))); 1.1155 + StartEntry(); 1.1156 + ASSERT_TRUE(handler.UndefinedRule(entry_address, 10)); 1.1157 + ASSERT_TRUE(handler.End()); 1.1158 + CheckEntry(); 1.1159 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1160 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1161 + } 1.1162 + 1.1163 + TEST_F(Rule, SameValueRule) { 1.1164 + StartEntry(); 1.1165 + ASSERT_TRUE(handler.SameValueRule(entry_address, 6)); 1.1166 + ASSERT_TRUE(handler.End()); 1.1167 + CheckEntry(); 1.1168 + Module::RuleMap expected_initial; 1.1169 +- expected_initial["reg6"] = Module::Expr("reg6", 0, false); 1.1170 ++ const UniqueString* reg6 = ToUniqueString("reg6"); 1.1171 ++ expected_initial[reg6] = Module::Expr(reg6, 0, false); 1.1172 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); 1.1173 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1174 + } 1.1175 + 1.1176 + TEST_F(Rule, OffsetRule) { 1.1177 + StartEntry(); 1.1178 + ASSERT_TRUE(handler.OffsetRule(entry_address + 1, return_reg, 1.1179 + DwarfCFIToModule::kCFARegister, 1.1180 + 16927065)); 1.1181 + ASSERT_TRUE(handler.End()); 1.1182 + CheckEntry(); 1.1183 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1184 + Module::RuleChangeMap expected_changes; 1.1185 +- expected_changes[entry_address + 1][".ra"] = 1.1186 +- Module::Expr(".cfa", 16927065, true); 1.1187 ++ expected_changes[entry_address + 1][ustr__ZDra()] = 1.1188 ++ Module::Expr(ustr__ZDcfa(), 16927065, true); 1.1189 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); 1.1190 + } 1.1191 + 1.1192 + TEST_F(Rule, OffsetRuleNegative) { 1.1193 + StartEntry(); 1.1194 + ASSERT_TRUE(handler.OffsetRule(entry_address + 1, 1.1195 + DwarfCFIToModule::kCFARegister, 4, -34530721)); 1.1196 + ASSERT_TRUE(handler.End()); 1.1197 + CheckEntry(); 1.1198 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1199 + Module::RuleChangeMap expected_changes; 1.1200 +- expected_changes[entry_address + 1][".cfa"] = 1.1201 +- Module::Expr("reg4", -34530721, true); 1.1202 ++ expected_changes[entry_address + 1][ustr__ZDcfa()] = 1.1203 ++ Module::Expr(ToUniqueString("reg4"), -34530721, true); 1.1204 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); 1.1205 + } 1.1206 + 1.1207 + TEST_F(Rule, ValOffsetRule) { 1.1208 + // Use an unnamed register number, to exercise that branch of RegisterName. 1.1209 + EXPECT_CALL(reporter, UnnamedRegister(_, 11)); 1.1210 + StartEntry(); 1.1211 + ASSERT_TRUE(handler.ValOffsetRule(entry_address + 0x5ab7, 1.1212 + DwarfCFIToModule::kCFARegister, 1.1213 + 11, 61812979)); 1.1214 + ASSERT_TRUE(handler.End()); 1.1215 + CheckEntry(); 1.1216 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1217 + Module::RuleChangeMap expected_changes; 1.1218 +- expected_changes[entry_address + 0x5ab7][".cfa"] = 1.1219 +- Module::Expr("unnamed_register11", 61812979, false); 1.1220 ++ expected_changes[entry_address + 0x5ab7][ustr__ZDcfa()] = 1.1221 ++ Module::Expr(ToUniqueString("unnamed_register11"), 61812979, false); 1.1222 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); 1.1223 + } 1.1224 + 1.1225 + TEST_F(Rule, RegisterRule) { 1.1226 + StartEntry(); 1.1227 + ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 3)); 1.1228 + ASSERT_TRUE(handler.End()); 1.1229 + CheckEntry(); 1.1230 + Module::RuleMap expected_initial; 1.1231 +- expected_initial[".ra"] = Module::Expr("reg3", 0, false); 1.1232 ++ expected_initial[ustr__ZDra()] = 1.1233 ++ Module::Expr(ToUniqueString("reg3"), 0, false); 1.1234 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); 1.1235 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1236 + } 1.1237 + 1.1238 + TEST_F(Rule, ExpressionRule) { 1.1239 +- EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg2")); 1.1240 ++ EXPECT_CALL(reporter, ExpressionsNotSupported(_, ToUniqueString("reg2"))); 1.1241 + StartEntry(); 1.1242 + ASSERT_TRUE(handler.ExpressionRule(entry_address + 0xf326, 2, 1.1243 + "it takes two to tango")); 1.1244 + ASSERT_TRUE(handler.End()); 1.1245 + CheckEntry(); 1.1246 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1247 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1248 + } 1.1249 + 1.1250 + TEST_F(Rule, ValExpressionRule) { 1.1251 +- EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg0")); 1.1252 ++ EXPECT_CALL(reporter, ExpressionsNotSupported(_, ToUniqueString("reg0"))); 1.1253 + StartEntry(); 1.1254 + ASSERT_TRUE(handler.ValExpressionRule(entry_address + 0x6367, 0, 1.1255 + "bit off more than he could chew")); 1.1256 + ASSERT_TRUE(handler.End()); 1.1257 + CheckEntry(); 1.1258 + EXPECT_EQ(0U, entries[0]->initial_rules.size()); 1.1259 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1260 + } 1.1261 + 1.1262 + TEST_F(Rule, DefaultReturnAddressRule) { 1.1263 + return_reg = 2; 1.1264 + StartEntry(); 1.1265 + ASSERT_TRUE(handler.RegisterRule(entry_address, 0, 1)); 1.1266 + ASSERT_TRUE(handler.End()); 1.1267 + CheckEntry(); 1.1268 + Module::RuleMap expected_initial; 1.1269 +- expected_initial[".ra"] = Module::Expr("reg2", 0, false); 1.1270 +- expected_initial["reg0"] = Module::Expr("reg1", 0, false); 1.1271 ++ expected_initial[ustr__ZDra()] = 1.1272 ++ Module::Expr(ToUniqueString("reg2"), 0, false); 1.1273 ++ expected_initial[ToUniqueString("reg0")] = 1.1274 ++ Module::Expr(ToUniqueString("reg1"), 0, false); 1.1275 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); 1.1276 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1277 + } 1.1278 + 1.1279 + TEST_F(Rule, DefaultReturnAddressRuleOverride) { 1.1280 + return_reg = 2; 1.1281 + StartEntry(); 1.1282 + ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 1)); 1.1283 + ASSERT_TRUE(handler.End()); 1.1284 + CheckEntry(); 1.1285 + Module::RuleMap expected_initial; 1.1286 +- expected_initial[".ra"] = Module::Expr("reg1", 0, false); 1.1287 ++ expected_initial[ustr__ZDra()] = 1.1288 ++ Module::Expr(ToUniqueString("reg1"), 0, false); 1.1289 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); 1.1290 + EXPECT_EQ(0U, entries[0]->rule_changes.size()); 1.1291 + } 1.1292 + 1.1293 + TEST_F(Rule, DefaultReturnAddressRuleLater) { 1.1294 + return_reg = 2; 1.1295 + StartEntry(); 1.1296 + ASSERT_TRUE(handler.RegisterRule(entry_address + 1, return_reg, 1)); 1.1297 + ASSERT_TRUE(handler.End()); 1.1298 + CheckEntry(); 1.1299 + Module::RuleMap expected_initial; 1.1300 +- expected_initial[".ra"] = Module::Expr("reg2", 0, false); 1.1301 ++ expected_initial[ustr__ZDra()] = 1.1302 ++ Module::Expr(ToUniqueString("reg2"), 0, false); 1.1303 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); 1.1304 + Module::RuleChangeMap expected_changes; 1.1305 +- expected_changes[entry_address + 1][".ra"] = 1.1306 +- Module::Expr("reg1", 0, false); 1.1307 ++ expected_changes[entry_address + 1][ustr__ZDra()] = 1.1308 ++ Module::Expr(ToUniqueString("reg1"), 0, false); 1.1309 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); 1.1310 + } 1.1311 + 1.1312 + TEST(RegisterNames, I386) { 1.1313 +- vector<string> names = DwarfCFIToModule::RegisterNames::I386(); 1.1314 ++ vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::I386(); 1.1315 + 1.1316 +- EXPECT_EQ("$eax", names[0]); 1.1317 +- EXPECT_EQ("$ecx", names[1]); 1.1318 +- EXPECT_EQ("$esp", names[4]); 1.1319 +- EXPECT_EQ("$eip", names[8]); 1.1320 ++ EXPECT_EQ(ToUniqueString("$eax"), names[0]); 1.1321 ++ EXPECT_EQ(ToUniqueString("$ecx"), names[1]); 1.1322 ++ EXPECT_EQ(ToUniqueString("$esp"), names[4]); 1.1323 ++ EXPECT_EQ(ToUniqueString("$eip"), names[8]); 1.1324 + } 1.1325 + 1.1326 + TEST(RegisterNames, ARM) { 1.1327 +- vector<string> names = DwarfCFIToModule::RegisterNames::ARM(); 1.1328 ++ vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::ARM(); 1.1329 + 1.1330 +- EXPECT_EQ("r0", names[0]); 1.1331 +- EXPECT_EQ("r10", names[10]); 1.1332 +- EXPECT_EQ("sp", names[13]); 1.1333 +- EXPECT_EQ("lr", names[14]); 1.1334 +- EXPECT_EQ("pc", names[15]); 1.1335 ++ EXPECT_EQ(ToUniqueString("r0"), names[0]); 1.1336 ++ EXPECT_EQ(ToUniqueString("r10"), names[10]); 1.1337 ++ EXPECT_EQ(ToUniqueString("sp"), names[13]); 1.1338 ++ EXPECT_EQ(ToUniqueString("lr"), names[14]); 1.1339 ++ EXPECT_EQ(ToUniqueString("pc"), names[15]); 1.1340 + } 1.1341 + 1.1342 + TEST(RegisterNames, X86_64) { 1.1343 +- vector<string> names = DwarfCFIToModule::RegisterNames::X86_64(); 1.1344 ++ vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::X86_64(); 1.1345 + 1.1346 +- EXPECT_EQ("$rax", names[0]); 1.1347 +- EXPECT_EQ("$rdx", names[1]); 1.1348 +- EXPECT_EQ("$rbp", names[6]); 1.1349 +- EXPECT_EQ("$rsp", names[7]); 1.1350 +- EXPECT_EQ("$rip", names[16]); 1.1351 ++ EXPECT_EQ(ToUniqueString("$rax"), names[0]); 1.1352 ++ EXPECT_EQ(ToUniqueString("$rdx"), names[1]); 1.1353 ++ EXPECT_EQ(ToUniqueString("$rbp"), names[6]); 1.1354 ++ EXPECT_EQ(ToUniqueString("$rsp"), names[7]); 1.1355 ++ EXPECT_EQ(ToUniqueString("$rip"), names[16]); 1.1356 + } 1.1357 +diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc 1.1358 +--- a/src/common/linux/dump_symbols.cc 1.1359 ++++ b/src/common/linux/dump_symbols.cc 1.1360 +@@ -81,16 +81,17 @@ 1.1361 + using google_breakpad::ElfClass64; 1.1362 + using google_breakpad::FindElfSectionByName; 1.1363 + using google_breakpad::GetOffset; 1.1364 + using google_breakpad::IsValidElf; 1.1365 + using google_breakpad::Module; 1.1366 + #ifndef NO_STABS_SUPPORT 1.1367 + using google_breakpad::StabsToModule; 1.1368 + #endif 1.1369 ++using google_breakpad::UniqueString; 1.1370 + using google_breakpad::scoped_ptr; 1.1371 + 1.1372 + // 1.1373 + // FDWrapper 1.1374 + // 1.1375 + // Wrapper class to make sure opened file is closed. 1.1376 + // 1.1377 + class FDWrapper { 1.1378 +@@ -278,17 +279,17 @@ 1.1379 + 1.1380 + // Fill REGISTER_NAMES with the register names appropriate to the 1.1381 + // machine architecture given in HEADER, indexed by the register 1.1382 + // numbers used in DWARF call frame information. Return true on 1.1383 + // success, or false if HEADER's machine architecture is not 1.1384 + // supported. 1.1385 + template<typename ElfClass> 1.1386 + bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header, 1.1387 +- std::vector<string>* register_names) { 1.1388 ++ std::vector<const UniqueString*>* register_names) { 1.1389 + switch (elf_header->e_machine) { 1.1390 + case EM_386: 1.1391 + *register_names = DwarfCFIToModule::RegisterNames::I386(); 1.1392 + return true; 1.1393 + case EM_ARM: 1.1394 + *register_names = DwarfCFIToModule::RegisterNames::ARM(); 1.1395 + return true; 1.1396 + case EM_X86_64: 1.1397 +@@ -306,17 +307,17 @@ 1.1398 + const typename ElfClass::Shdr* section, 1.1399 + const bool eh_frame, 1.1400 + const typename ElfClass::Shdr* got_section, 1.1401 + const typename ElfClass::Shdr* text_section, 1.1402 + const bool big_endian, 1.1403 + Module* module) { 1.1404 + // Find the appropriate set of register names for this file's 1.1405 + // architecture. 1.1406 +- std::vector<string> register_names; 1.1407 ++ std::vector<const UniqueString*> register_names; 1.1408 + if (!DwarfCFIRegisterNames<ElfClass>(elf_header, ®ister_names)) { 1.1409 + fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';" 1.1410 + " cannot convert DWARF call frame information\n", 1.1411 + dwarf_filename.c_str(), elf_header->e_machine); 1.1412 + return false; 1.1413 + } 1.1414 + 1.1415 + const dwarf2reader::Endianness endianness = big_endian ? 1.1416 +diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.mm 1.1417 +--- a/src/common/mac/dump_syms.mm 1.1418 ++++ b/src/common/mac/dump_syms.mm 1.1419 +@@ -313,17 +313,17 @@ 1.1420 + } 1.1421 + 1.1422 + bool DumpSymbols::ReadCFI(google_breakpad::Module *module, 1.1423 + const mach_o::Reader &macho_reader, 1.1424 + const mach_o::Section §ion, 1.1425 + bool eh_frame) const { 1.1426 + // Find the appropriate set of register names for this file's 1.1427 + // architecture. 1.1428 +- vector<string> register_names; 1.1429 ++ vector<const UniqueString*> register_names; 1.1430 + switch (macho_reader.cpu_type()) { 1.1431 + case CPU_TYPE_X86: 1.1432 + register_names = DwarfCFIToModule::RegisterNames::I386(); 1.1433 + break; 1.1434 + case CPU_TYPE_X86_64: 1.1435 + register_names = DwarfCFIToModule::RegisterNames::X86_64(); 1.1436 + break; 1.1437 + case CPU_TYPE_ARM: 1.1438 +diff --git a/src/common/module.cc b/src/common/module.cc 1.1439 +--- a/src/common/module.cc 1.1440 ++++ b/src/common/module.cc 1.1441 +@@ -33,16 +33,17 @@ 1.1442 + 1.1443 + #include "common/module.h" 1.1444 + 1.1445 + #include <assert.h> 1.1446 + #include <errno.h> 1.1447 + #include <stdio.h> 1.1448 + #include <string.h> 1.1449 + 1.1450 ++#include <algorithm> 1.1451 + #include <iostream> 1.1452 + #include <utility> 1.1453 + 1.1454 + namespace google_breakpad { 1.1455 + 1.1456 + using std::dec; 1.1457 + using std::endl; 1.1458 + using std::hex; 1.1459 +@@ -255,36 +256,50 @@ 1.1460 + strerror(errno)); 1.1461 + return false; 1.1462 + } 1.1463 + 1.1464 + std::ostream& operator<<(std::ostream& stream, const Module::Expr& expr) { 1.1465 + assert(!expr.invalid()); 1.1466 + switch (expr.how_) { 1.1467 + case Module::kExprSimple: 1.1468 +- stream << expr.ident_ << " " << expr.offset_ << " +"; 1.1469 ++ stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " +"; 1.1470 + break; 1.1471 + case Module::kExprSimpleMem: 1.1472 +- stream << expr.ident_ << " " << expr.offset_ << " + ^"; 1.1473 ++ stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " + ^"; 1.1474 + break; 1.1475 + case Module::kExprPostfix: 1.1476 + stream << expr.postfix_; break; 1.1477 + case Module::kExprInvalid: 1.1478 + default: 1.1479 + break; 1.1480 + } 1.1481 + return stream; 1.1482 + } 1.1483 + 1.1484 + bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) { 1.1485 ++ // Visit the register rules in alphabetical order. Because 1.1486 ++ // rule_map has the elements in some arbitrary order, 1.1487 ++ // get the names out into a vector, sort them, and visit in 1.1488 ++ // sorted order. 1.1489 ++ std::vector<const UniqueString*> rr_names; 1.1490 + for (RuleMap::const_iterator it = rule_map.begin(); 1.1491 + it != rule_map.end(); ++it) { 1.1492 +- if (it != rule_map.begin()) 1.1493 +- stream << ' '; 1.1494 +- stream << it->first << ": " << it->second; 1.1495 ++ rr_names.push_back(it->first); 1.1496 ++ } 1.1497 ++ 1.1498 ++ std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString); 1.1499 ++ 1.1500 ++ // Now visit the register rules in alphabetical order. 1.1501 ++ for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin(); 1.1502 ++ name != rr_names.end(); 1.1503 ++ ++name) { 1.1504 ++ if (name != rr_names.begin()) 1.1505 ++ stream << " "; 1.1506 ++ stream << FromUniqueString(*name) << ": " << rule_map.find(*name)->second; 1.1507 + } 1.1508 + return stream.good(); 1.1509 + } 1.1510 + 1.1511 + bool Module::Write(std::ostream &stream, SymbolData symbol_data) { 1.1512 + stream << "MODULE " << os_ << " " << architecture_ << " " 1.1513 + << id_ << " " << name_ << endl; 1.1514 + if (!stream.good()) 1.1515 +diff --git a/src/common/module.h b/src/common/module.h 1.1516 +--- a/src/common/module.h 1.1517 ++++ b/src/common/module.h 1.1518 +@@ -41,16 +41,17 @@ 1.1519 + #include <iostream> 1.1520 + #include <map> 1.1521 + #include <set> 1.1522 + #include <string> 1.1523 + #include <vector> 1.1524 + 1.1525 + #include "common/symbol_data.h" 1.1526 + #include "common/using_std_string.h" 1.1527 ++#include "common/unique_string.h" 1.1528 + #include "google_breakpad/common/breakpad_types.h" 1.1529 + 1.1530 + namespace google_breakpad { 1.1531 + 1.1532 + using std::set; 1.1533 + using std::vector; 1.1534 + using std::map; 1.1535 + 1.1536 +@@ -131,69 +132,69 @@ 1.1537 + enum ExprHow { 1.1538 + kExprInvalid = 1, 1.1539 + kExprPostfix, 1.1540 + kExprSimple, 1.1541 + kExprSimpleMem 1.1542 + }; 1.1543 + struct Expr { 1.1544 + // Construct a simple-form expression 1.1545 +- Expr(string ident, long offset, bool deref) { 1.1546 +- if (ident.empty()) { 1.1547 ++ Expr(const UniqueString* ident, long offset, bool deref) { 1.1548 ++ if (ident == ustr__empty()) { 1.1549 + Expr(); 1.1550 + } else { 1.1551 + postfix_ = ""; 1.1552 + ident_ = ident; 1.1553 + offset_ = offset; 1.1554 + how_ = deref ? kExprSimpleMem : kExprSimple; 1.1555 + } 1.1556 + } 1.1557 + // Construct an expression from a postfix string 1.1558 + Expr(string postfix) { 1.1559 + if (postfix.empty()) { 1.1560 + Expr(); 1.1561 + } else { 1.1562 + postfix_ = postfix; 1.1563 +- ident_ = ""; 1.1564 ++ ident_ = NULL; 1.1565 + offset_ = 0; 1.1566 + how_ = kExprPostfix; 1.1567 + } 1.1568 + } 1.1569 + // Construct an invalid expression 1.1570 + Expr() { 1.1571 + postfix_ = ""; 1.1572 +- ident_ = ""; 1.1573 ++ ident_ = NULL; 1.1574 + offset_ = 0; 1.1575 + how_ = kExprInvalid; 1.1576 + } 1.1577 + bool invalid() const { return how_ == kExprInvalid; } 1.1578 + bool operator==(const Expr& other) const { 1.1579 + return how_ == other.how_ && 1.1580 + ident_ == other.ident_ && 1.1581 + offset_ == other.offset_ && 1.1582 + postfix_ == other.postfix_; 1.1583 + } 1.1584 + 1.1585 + // The identifier that gives the starting value for simple expressions. 1.1586 +- string ident_; 1.1587 ++ const UniqueString* ident_; 1.1588 + // The offset to add for simple expressions. 1.1589 + long offset_; 1.1590 + // The Postfix expression string to evaluate for non-simple expressions. 1.1591 + string postfix_; 1.1592 + // The operation expressed by this expression. 1.1593 + ExprHow how_; 1.1594 + 1.1595 + friend std::ostream& operator<<(std::ostream& stream, const Expr& expr); 1.1596 + }; 1.1597 + 1.1598 + // A map from register names to expressions that recover 1.1599 + // their values. This can represent a complete set of rules to 1.1600 + // follow at some address, or a set of changes to be applied to an 1.1601 + // extant set of rules. 1.1602 +- typedef map<string, Expr> RuleMap; 1.1603 ++ typedef map<const UniqueString*, Expr> RuleMap; 1.1604 + 1.1605 + // A map from addresses to RuleMaps, representing changes that take 1.1606 + // effect at given addresses. 1.1607 + typedef map<Address, RuleMap> RuleChangeMap; 1.1608 + 1.1609 + // A range of 'STACK CFI' stack walking information. An instance of 1.1610 + // this structure corresponds to a 'STACK CFI INIT' record and the 1.1611 + // subsequent 'STACK CFI' records that fall within its range. 1.1612 +diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc 1.1613 +--- a/src/common/module_unittest.cc 1.1614 ++++ b/src/common/module_unittest.cc 1.1615 +@@ -40,16 +40,18 @@ 1.1616 + #include <sstream> 1.1617 + #include <string> 1.1618 + 1.1619 + #include "breakpad_googletest_includes.h" 1.1620 + #include "common/module.h" 1.1621 + #include "common/using_std_string.h" 1.1622 + 1.1623 + using google_breakpad::Module; 1.1624 ++using google_breakpad::ToUniqueString; 1.1625 ++using google_breakpad::ustr__ZDcfa; 1.1626 + using std::stringstream; 1.1627 + using std::vector; 1.1628 + using testing::ContainerEq; 1.1629 + 1.1630 + static Module::Function *generate_duplicate_function(const string &name) { 1.1631 + const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL; 1.1632 + const Module::Address DUP_SIZE = 0x200b26e605f99071LL; 1.1633 + const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL; 1.1634 +@@ -125,21 +127,27 @@ 1.1635 + function->lines.push_back(line1); 1.1636 + 1.1637 + m.AddFunction(function); 1.1638 + 1.1639 + // Some stack information. 1.1640 + Module::StackFrameEntry *entry = new Module::StackFrameEntry(); 1.1641 + entry->address = 0x30f9e5c83323973dULL; 1.1642 + entry->size = 0x49fc9ca7c7c13dc2ULL; 1.1643 +- entry->initial_rules[".cfa"] = Module::Expr("he was a handsome man"); 1.1644 +- entry->initial_rules["and"] = Module::Expr("what i want to know is"); 1.1645 +- entry->rule_changes[0x30f9e5c83323973eULL]["how"] = 1.1646 +- Module::Expr("do you like your blueeyed boy"); 1.1647 +- entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = Module::Expr("Death"); 1.1648 ++ entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man"); 1.1649 ++ entry->initial_rules[ToUniqueString("and")] = 1.1650 ++ Module::Expr("what i want to know is"); 1.1651 ++ entry->initial_rules[ToUniqueString("stallion")] = 1.1652 ++ Module::Expr(ToUniqueString("and break"), 8, false); 1.1653 ++ entry->initial_rules[ToUniqueString("onetwothreefourfive")] = 1.1654 ++ Module::Expr(ToUniqueString("pigeonsjustlikethat"), 42, true); 1.1655 ++ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] = 1.1656 ++ Module::Expr("do you like your blueeyed boy"); 1.1657 ++ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] = 1.1658 ++ Module::Expr("Death"); 1.1659 + m.AddStackFrameEntry(entry); 1.1660 + 1.1661 + // Set the load address. Doing this after adding all the data to 1.1662 + // the module must work fine. 1.1663 + m.SetLoadAddress(0x2ab698b0b6407073LL); 1.1664 + 1.1665 + m.Write(s, ALL_SYMBOL_DATA); 1.1666 + string contents = s.str(); 1.1667 +@@ -147,17 +155,19 @@ 1.1668 + "FILE 0 filename-a.cc\n" 1.1669 + "FILE 1 filename-b.cc\n" 1.1670 + "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0" 1.1671 + " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n" 1.1672 + "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n" 1.1673 + "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n" 1.1674 + "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2" 1.1675 + " .cfa: he was a handsome man" 1.1676 +- " and: what i want to know is\n" 1.1677 ++ " and: what i want to know is" 1.1678 ++ " onetwothreefourfive: pigeonsjustlikethat 42 + ^" 1.1679 ++ " stallion: and break 8 +\n" 1.1680 + "STACK CFI 6434d177ce326cb" 1.1681 + " Mister: Death" 1.1682 + " how: do you like your blueeyed boy\n", 1.1683 + contents.c_str()); 1.1684 + } 1.1685 + 1.1686 + TEST(Write, OmitUnusedFiles) { 1.1687 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.1688 +@@ -229,21 +239,23 @@ 1.1689 + function->lines.push_back(line1); 1.1690 + 1.1691 + m.AddFunction(function); 1.1692 + 1.1693 + // Some stack information. 1.1694 + Module::StackFrameEntry *entry = new Module::StackFrameEntry(); 1.1695 + entry->address = 0x30f9e5c83323973dULL; 1.1696 + entry->size = 0x49fc9ca7c7c13dc2ULL; 1.1697 +- entry->initial_rules[".cfa"] = Module::Expr("he was a handsome man"); 1.1698 +- entry->initial_rules["and"] = Module::Expr("what i want to know is"); 1.1699 +- entry->rule_changes[0x30f9e5c83323973eULL]["how"] = 1.1700 +- Module::Expr("do you like your blueeyed boy"); 1.1701 +- entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = Module::Expr("Death"); 1.1702 ++ entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man"); 1.1703 ++ entry->initial_rules[ToUniqueString("and")] = 1.1704 ++ Module::Expr("what i want to know is"); 1.1705 ++ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] = 1.1706 ++ Module::Expr("do you like your blueeyed boy"); 1.1707 ++ entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] = 1.1708 ++ Module::Expr("Death"); 1.1709 + m.AddStackFrameEntry(entry); 1.1710 + 1.1711 + // Set the load address. Doing this after adding all the data to 1.1712 + // the module must work fine. 1.1713 + m.SetLoadAddress(0x2ab698b0b6407073LL); 1.1714 + 1.1715 + m.Write(s, NO_CFI); 1.1716 + string contents = s.str(); 1.1717 +@@ -305,33 +317,36 @@ 1.1718 + entry1->address = 0xddb5f41285aa7757ULL; 1.1719 + entry1->size = 0x1486493370dc5073ULL; 1.1720 + m.AddStackFrameEntry(entry1); 1.1721 + 1.1722 + // Second STACK CFI entry, with initial rules but no deltas. 1.1723 + Module::StackFrameEntry *entry2 = new Module::StackFrameEntry(); 1.1724 + entry2->address = 0x8064f3af5e067e38ULL; 1.1725 + entry2->size = 0x0de2a5ee55509407ULL; 1.1726 +- entry2->initial_rules[".cfa"] = Module::Expr("I think that I shall never see"); 1.1727 +- entry2->initial_rules["stromboli"] = Module::Expr("a poem lovely as a tree"); 1.1728 +- entry2->initial_rules["cannoli"] = Module::Expr("a tree whose hungry mouth is prest"); 1.1729 ++ entry2->initial_rules[ustr__ZDcfa()] = 1.1730 ++ Module::Expr("I think that I shall never see"); 1.1731 ++ entry2->initial_rules[ToUniqueString("stromboli")] = 1.1732 ++ Module::Expr("a poem lovely as a tree"); 1.1733 ++ entry2->initial_rules[ToUniqueString("cannoli")] = 1.1734 ++ Module::Expr("a tree whose hungry mouth is prest"); 1.1735 + m.AddStackFrameEntry(entry2); 1.1736 + 1.1737 + // Third STACK CFI entry, with initial rules and deltas. 1.1738 + Module::StackFrameEntry *entry3 = new Module::StackFrameEntry(); 1.1739 + entry3->address = 0x5e8d0db0a7075c6cULL; 1.1740 + entry3->size = 0x1c7edb12a7aea229ULL; 1.1741 +- entry3->initial_rules[".cfa"] = Module::Expr("Whose woods are these"); 1.1742 +- entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] = 1.1743 ++ entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these"); 1.1744 ++ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] = 1.1745 + Module::Expr("the village though"); 1.1746 +- entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] = 1.1747 ++ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] = 1.1748 + Module::Expr("he will not see me stopping here"); 1.1749 +- entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] = 1.1750 ++ entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] = 1.1751 + Module::Expr("his house is in"); 1.1752 +- entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] = 1.1753 ++ entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] = 1.1754 + Module::Expr("I think I know"); 1.1755 + m.AddStackFrameEntry(entry3); 1.1756 + 1.1757 + // Check that Write writes STACK CFI records properly. 1.1758 + m.Write(s, ALL_SYMBOL_DATA); 1.1759 + string contents = s.str(); 1.1760 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.1761 + "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229" 1.1762 +@@ -352,33 +367,39 @@ 1.1763 + // Check that GetStackFrameEntries works. 1.1764 + vector<Module::StackFrameEntry *> entries; 1.1765 + m.GetStackFrameEntries(&entries); 1.1766 + ASSERT_EQ(3U, entries.size()); 1.1767 + // Check first entry. 1.1768 + EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address); 1.1769 + EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size); 1.1770 + Module::RuleMap entry1_initial; 1.1771 +- entry1_initial[".cfa"] = Module::Expr("Whose woods are these"); 1.1772 ++ entry1_initial[ustr__ZDcfa()] = Module::Expr("Whose woods are these"); 1.1773 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial)); 1.1774 + Module::RuleChangeMap entry1_changes; 1.1775 +- entry1_changes[0x36682fad3763ffffULL][".cfa"] = Module::Expr("I think I know"); 1.1776 +- entry1_changes[0x36682fad3763ffffULL]["stromboli"] = Module::Expr("his house is in"); 1.1777 +- entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = Module::Expr("the village though"); 1.1778 +- entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] = 1.1779 +- Module::Expr("he will not see me stopping here"); 1.1780 ++ entry1_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] = 1.1781 ++ Module::Expr("I think I know"); 1.1782 ++ entry1_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] = 1.1783 ++ Module::Expr("his house is in"); 1.1784 ++ entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] = 1.1785 ++ Module::Expr("the village though"); 1.1786 ++ entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] = 1.1787 ++ Module::Expr("he will not see me stopping here"); 1.1788 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes)); 1.1789 + // Check second entry. 1.1790 + EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address); 1.1791 + EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size); 1.1792 + ASSERT_EQ(3U, entries[1]->initial_rules.size()); 1.1793 + Module::RuleMap entry2_initial; 1.1794 +- entry2_initial[".cfa"] = Module::Expr("I think that I shall never see"); 1.1795 +- entry2_initial["stromboli"] = Module::Expr("a poem lovely as a tree"); 1.1796 +- entry2_initial["cannoli"] = Module::Expr("a tree whose hungry mouth is prest"); 1.1797 ++ entry2_initial[ustr__ZDcfa()] = 1.1798 ++ Module::Expr("I think that I shall never see"); 1.1799 ++ entry2_initial[ToUniqueString("stromboli")] = 1.1800 ++ Module::Expr("a poem lovely as a tree"); 1.1801 ++ entry2_initial[ToUniqueString("cannoli")] = 1.1802 ++ Module::Expr("a tree whose hungry mouth is prest"); 1.1803 + EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial)); 1.1804 + ASSERT_EQ(0U, entries[1]->rule_changes.size()); 1.1805 + // Check third entry. 1.1806 + EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address); 1.1807 + EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size); 1.1808 + ASSERT_EQ(0U, entries[2]->initial_rules.size()); 1.1809 + ASSERT_EQ(0U, entries[2]->rule_changes.size()); 1.1810 + } 1.1811 +@@ -585,33 +606,36 @@ 1.1812 + entry1->address = 0x2000; 1.1813 + entry1->size = 0x900; 1.1814 + m.AddStackFrameEntry(entry1); 1.1815 + 1.1816 + // Second STACK CFI entry, with initial rules but no deltas. 1.1817 + Module::StackFrameEntry *entry2 = new Module::StackFrameEntry(); 1.1818 + entry2->address = 0x3000; 1.1819 + entry2->size = 0x900; 1.1820 +- entry2->initial_rules[".cfa"] = Module::Expr("I think that I shall never see"); 1.1821 +- entry2->initial_rules["stromboli"] = Module::Expr("a poem lovely as a tree"); 1.1822 +- entry2->initial_rules["cannoli"] = Module::Expr("a tree whose hungry mouth is prest"); 1.1823 ++ entry2->initial_rules[ustr__ZDcfa()] = 1.1824 ++ Module::Expr("I think that I shall never see"); 1.1825 ++ entry2->initial_rules[ToUniqueString("stromboli")] = 1.1826 ++ Module::Expr("a poem lovely as a tree"); 1.1827 ++ entry2->initial_rules[ToUniqueString("cannoli")] = 1.1828 ++ Module::Expr("a tree whose hungry mouth is prest"); 1.1829 + m.AddStackFrameEntry(entry2); 1.1830 + 1.1831 + // Third STACK CFI entry, with initial rules and deltas. 1.1832 + Module::StackFrameEntry *entry3 = new Module::StackFrameEntry(); 1.1833 + entry3->address = 0x1000; 1.1834 + entry3->size = 0x900; 1.1835 +- entry3->initial_rules[".cfa"] = Module::Expr("Whose woods are these"); 1.1836 +- entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] = 1.1837 ++ entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these"); 1.1838 ++ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] = 1.1839 + Module::Expr("the village though"); 1.1840 +- entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] = 1.1841 ++ entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] = 1.1842 + Module::Expr("he will not see me stopping here"); 1.1843 +- entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] = 1.1844 ++ entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] = 1.1845 + Module::Expr("his house is in"); 1.1846 +- entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] = 1.1847 ++ entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] = 1.1848 + Module::Expr("I think I know"); 1.1849 + m.AddStackFrameEntry(entry3); 1.1850 + 1.1851 + Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000); 1.1852 + EXPECT_EQ(entry3, s); 1.1853 + s = m.FindStackFrameEntryByAddress(0x18FF); 1.1854 + EXPECT_EQ(entry3, s); 1.1855 + 1.1856 +diff --git a/src/common/unique_string.cc b/src/common/unique_string.cc 1.1857 +new file mode 100644 1.1858 +--- /dev/null 1.1859 ++++ b/src/common/unique_string.cc 1.1860 +@@ -0,0 +1,110 @@ 1.1861 ++// Copyright (c) 2013 Google Inc. 1.1862 ++// All rights reserved. 1.1863 ++// 1.1864 ++// Redistribution and use in source and binary forms, with or without 1.1865 ++// modification, are permitted provided that the following conditions are 1.1866 ++// met: 1.1867 ++// 1.1868 ++// * Redistributions of source code must retain the above copyright 1.1869 ++// notice, this list of conditions and the following disclaimer. 1.1870 ++// * Redistributions in binary form must reproduce the above 1.1871 ++// copyright notice, this list of conditions and the following disclaimer 1.1872 ++// in the documentation and/or other materials provided with the 1.1873 ++// distribution. 1.1874 ++// * Neither the name of Google Inc. nor the names of its 1.1875 ++// contributors may be used to endorse or promote products derived from 1.1876 ++// this software without specific prior written permission. 1.1877 ++// 1.1878 ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.1879 ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.1880 ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.1881 ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.1882 ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.1883 ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.1884 ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.1885 ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.1886 ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.1887 ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.1888 ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.1889 ++ 1.1890 ++#include <string> 1.1891 ++#include <map> 1.1892 ++ 1.1893 ++#include <stdlib.h> 1.1894 ++#include <string.h> 1.1895 ++ 1.1896 ++#include "common/unique_string.h" 1.1897 ++ 1.1898 ++namespace google_breakpad { 1.1899 ++ 1.1900 ++/////////////////////////////////////////////////////////////////// 1.1901 ++// UniqueString 1.1902 ++// 1.1903 ++class UniqueString { 1.1904 ++ public: 1.1905 ++ UniqueString(string str) { str_ = strdup(str.c_str()); } 1.1906 ++ ~UniqueString() { free(reinterpret_cast<void*>(const_cast<char*>(str_))); } 1.1907 ++ const char* str_; 1.1908 ++}; 1.1909 ++ 1.1910 ++class UniqueStringUniverse { 1.1911 ++ public: 1.1912 ++ UniqueStringUniverse() {}; 1.1913 ++ const UniqueString* FindOrCopy(string str) { 1.1914 ++ std::map<string, UniqueString*>::iterator it = map_.find(str); 1.1915 ++ if (it == map_.end()) { 1.1916 ++ UniqueString* ustr = new UniqueString(str); 1.1917 ++ map_[str] = ustr; 1.1918 ++ return ustr; 1.1919 ++ } else { 1.1920 ++ return it->second; 1.1921 ++ } 1.1922 ++ } 1.1923 ++ private: 1.1924 ++ std::map<string, UniqueString*> map_; 1.1925 ++}; 1.1926 ++ 1.1927 ++// 1.1928 ++/////////////////////////////////////////////////////////////////// 1.1929 ++ 1.1930 ++ 1.1931 ++static UniqueStringUniverse* sUSU = NULL; 1.1932 ++ 1.1933 ++ 1.1934 ++// This isn't threadsafe. 1.1935 ++const UniqueString* ToUniqueString(string str) { 1.1936 ++ if (!sUSU) { 1.1937 ++ sUSU = new UniqueStringUniverse(); 1.1938 ++ } 1.1939 ++ return sUSU->FindOrCopy(str); 1.1940 ++} 1.1941 ++ 1.1942 ++// This isn't threadsafe. 1.1943 ++const UniqueString* ToUniqueString_n(const char* str, size_t n) { 1.1944 ++ if (!sUSU) { 1.1945 ++ sUSU = new UniqueStringUniverse(); 1.1946 ++ } 1.1947 ++ string key(str, n); 1.1948 ++ return sUSU->FindOrCopy(key); 1.1949 ++} 1.1950 ++ 1.1951 ++const char Index(const UniqueString* us, int ix) 1.1952 ++{ 1.1953 ++ return us->str_[ix]; 1.1954 ++} 1.1955 ++ 1.1956 ++const char* const FromUniqueString(const UniqueString* ustr) 1.1957 ++{ 1.1958 ++ return ustr->str_; 1.1959 ++} 1.1960 ++ 1.1961 ++int StrcmpUniqueString(const UniqueString* us1, const UniqueString* us2) { 1.1962 ++ return strcmp(us1->str_, us2->str_); 1.1963 ++} 1.1964 ++ 1.1965 ++bool LessThan_UniqueString(const UniqueString* us1, const UniqueString* us2) { 1.1966 ++ int r = StrcmpUniqueString(us1, us2); 1.1967 ++ return r < 0; 1.1968 ++} 1.1969 ++ 1.1970 ++} // namespace google_breakpad 1.1971 +diff --git a/src/common/unique_string.h b/src/common/unique_string.h 1.1972 +new file mode 100644 1.1973 +--- /dev/null 1.1974 ++++ b/src/common/unique_string.h 1.1975 +@@ -0,0 +1,239 @@ 1.1976 ++// Copyright (c) 2013 Google Inc. 1.1977 ++// All rights reserved. 1.1978 ++// 1.1979 ++// Redistribution and use in source and binary forms, with or without 1.1980 ++// modification, are permitted provided that the following conditions are 1.1981 ++// met: 1.1982 ++// 1.1983 ++// * Redistributions of source code must retain the above copyright 1.1984 ++// notice, this list of conditions and the following disclaimer. 1.1985 ++// * Redistributions in binary form must reproduce the above 1.1986 ++// copyright notice, this list of conditions and the following disclaimer 1.1987 ++// in the documentation and/or other materials provided with the 1.1988 ++// distribution. 1.1989 ++// * Neither the name of Google Inc. nor the names of its 1.1990 ++// contributors may be used to endorse or promote products derived from 1.1991 ++// this software without specific prior written permission. 1.1992 ++// 1.1993 ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.1994 ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.1995 ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.1996 ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.1997 ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.1998 ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.1999 ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.2000 ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.2001 ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.2002 ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.2003 ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.2004 ++ 1.2005 ++#ifndef COMMON_UNIQUE_STRING_H_ 1.2006 ++#define COMMON_UNIQUE_STRING_H_ 1.2007 ++ 1.2008 ++#include <string> 1.2009 ++#include "common/using_std_string.h" 1.2010 ++ 1.2011 ++namespace google_breakpad { 1.2012 ++ 1.2013 ++// Abstract type 1.2014 ++class UniqueString; 1.2015 ++ 1.2016 ++// Unique-ify a string. |ToUniqueString| can never return NULL. 1.2017 ++const UniqueString* ToUniqueString(string); 1.2018 ++ 1.2019 ++// ditto, starting instead from the first n characters of a C string 1.2020 ++const UniqueString* ToUniqueString_n(const char* str, size_t n); 1.2021 ++ 1.2022 ++// Pull chars out of the string. No range checking. 1.2023 ++const char Index(const UniqueString*, int); 1.2024 ++ 1.2025 ++// Get the contained C string (debugging only) 1.2026 ++const char* const FromUniqueString(const UniqueString*); 1.2027 ++ 1.2028 ++// Do a strcmp-style comparison on the contained C string 1.2029 ++int StrcmpUniqueString(const UniqueString*, const UniqueString*); 1.2030 ++ 1.2031 ++// Less-than comparison of two UniqueStrings, usable for std::sort. 1.2032 ++bool LessThan_UniqueString(const UniqueString*, const UniqueString*); 1.2033 ++ 1.2034 ++// Some handy pre-uniqified strings. Z is an escape character: 1.2035 ++// ZS '$' 1.2036 ++// ZD '.' 1.2037 ++// Zeq '=' 1.2038 ++// Zplus '+' 1.2039 ++// Zstar '*' 1.2040 ++// Zslash '/' 1.2041 ++// Zpercent '%' 1.2042 ++// Zat '@' 1.2043 ++// Zcaret '^' 1.2044 ++ 1.2045 ++// Note that ustr__empty and (UniqueString*)NULL are considered 1.2046 ++// to be different. 1.2047 ++// 1.2048 ++// Unfortunately these have to be written as functions so as to 1.2049 ++// make them safe to use in static initialisers. 1.2050 ++ 1.2051 ++// "" 1.2052 ++inline static const UniqueString* ustr__empty() { 1.2053 ++ static const UniqueString* us = NULL; 1.2054 ++ if (!us) us = ToUniqueString(""); 1.2055 ++ return us; 1.2056 ++} 1.2057 ++ 1.2058 ++// "$eip" 1.2059 ++inline static const UniqueString* ustr__ZSeip() { 1.2060 ++ static const UniqueString* us = NULL; 1.2061 ++ if (!us) us = ToUniqueString("$eip"); 1.2062 ++ return us; 1.2063 ++} 1.2064 ++ 1.2065 ++// "$ebp" 1.2066 ++inline static const UniqueString* ustr__ZSebp() { 1.2067 ++ static const UniqueString* us = NULL; 1.2068 ++ if (!us) us = ToUniqueString("$ebp"); 1.2069 ++ return us; 1.2070 ++} 1.2071 ++ 1.2072 ++// "$esp" 1.2073 ++inline static const UniqueString* ustr__ZSesp() { 1.2074 ++ static const UniqueString* us = NULL; 1.2075 ++ if (!us) us = ToUniqueString("$esp"); 1.2076 ++ return us; 1.2077 ++} 1.2078 ++ 1.2079 ++// "$ebx" 1.2080 ++inline static const UniqueString* ustr__ZSebx() { 1.2081 ++ static const UniqueString* us = NULL; 1.2082 ++ if (!us) us = ToUniqueString("$ebx"); 1.2083 ++ return us; 1.2084 ++} 1.2085 ++ 1.2086 ++// "$esi" 1.2087 ++inline static const UniqueString* ustr__ZSesi() { 1.2088 ++ static const UniqueString* us = NULL; 1.2089 ++ if (!us) us = ToUniqueString("$esi"); 1.2090 ++ return us; 1.2091 ++} 1.2092 ++ 1.2093 ++// "$edi" 1.2094 ++inline static const UniqueString* ustr__ZSedi() { 1.2095 ++ static const UniqueString* us = NULL; 1.2096 ++ if (!us) us = ToUniqueString("$edi"); 1.2097 ++ return us; 1.2098 ++} 1.2099 ++ 1.2100 ++// ".cbCalleeParams" 1.2101 ++inline static const UniqueString* ustr__ZDcbCalleeParams() { 1.2102 ++ static const UniqueString* us = NULL; 1.2103 ++ if (!us) us = ToUniqueString(".cbCalleeParams"); 1.2104 ++ return us; 1.2105 ++} 1.2106 ++ 1.2107 ++// ".cbSavedRegs" 1.2108 ++inline static const UniqueString* ustr__ZDcbSavedRegs() { 1.2109 ++ static const UniqueString* us = NULL; 1.2110 ++ if (!us) us = ToUniqueString(".cbSavedRegs"); 1.2111 ++ return us; 1.2112 ++} 1.2113 ++ 1.2114 ++// ".cbLocals" 1.2115 ++inline static const UniqueString* ustr__ZDcbLocals() { 1.2116 ++ static const UniqueString* us = NULL; 1.2117 ++ if (!us) us = ToUniqueString(".cbLocals"); 1.2118 ++ return us; 1.2119 ++} 1.2120 ++ 1.2121 ++// ".raSearchStart" 1.2122 ++inline static const UniqueString* ustr__ZDraSearchStart() { 1.2123 ++ static const UniqueString* us = NULL; 1.2124 ++ if (!us) us = ToUniqueString(".raSearchStart"); 1.2125 ++ return us; 1.2126 ++} 1.2127 ++ 1.2128 ++// ".raSearch" 1.2129 ++inline static const UniqueString* ustr__ZDraSearch() { 1.2130 ++ static const UniqueString* us = NULL; 1.2131 ++ if (!us) us = ToUniqueString(".raSearch"); 1.2132 ++ return us; 1.2133 ++} 1.2134 ++ 1.2135 ++// ".cbParams" 1.2136 ++inline static const UniqueString* ustr__ZDcbParams() { 1.2137 ++ static const UniqueString* us = NULL; 1.2138 ++ if (!us) us = ToUniqueString(".cbParams"); 1.2139 ++ return us; 1.2140 ++} 1.2141 ++ 1.2142 ++// "+" 1.2143 ++inline static const UniqueString* ustr__Zplus() { 1.2144 ++ static const UniqueString* us = NULL; 1.2145 ++ if (!us) us = ToUniqueString("+"); 1.2146 ++ return us; 1.2147 ++} 1.2148 ++ 1.2149 ++// "-" 1.2150 ++inline static const UniqueString* ustr__Zminus() { 1.2151 ++ static const UniqueString* us = NULL; 1.2152 ++ if (!us) us = ToUniqueString("-"); 1.2153 ++ return us; 1.2154 ++} 1.2155 ++ 1.2156 ++// "*" 1.2157 ++inline static const UniqueString* ustr__Zstar() { 1.2158 ++ static const UniqueString* us = NULL; 1.2159 ++ if (!us) us = ToUniqueString("*"); 1.2160 ++ return us; 1.2161 ++} 1.2162 ++ 1.2163 ++// "/" 1.2164 ++inline static const UniqueString* ustr__Zslash() { 1.2165 ++ static const UniqueString* us = NULL; 1.2166 ++ if (!us) us = ToUniqueString("/"); 1.2167 ++ return us; 1.2168 ++} 1.2169 ++ 1.2170 ++// "%" 1.2171 ++inline static const UniqueString* ustr__Zpercent() { 1.2172 ++ static const UniqueString* us = NULL; 1.2173 ++ if (!us) us = ToUniqueString("%"); 1.2174 ++ return us; 1.2175 ++} 1.2176 ++ 1.2177 ++// "@" 1.2178 ++inline static const UniqueString* ustr__Zat() { 1.2179 ++ static const UniqueString* us = NULL; 1.2180 ++ if (!us) us = ToUniqueString("@"); 1.2181 ++ return us; 1.2182 ++} 1.2183 ++ 1.2184 ++// "^" 1.2185 ++inline static const UniqueString* ustr__Zcaret() { 1.2186 ++ static const UniqueString* us = NULL; 1.2187 ++ if (!us) us = ToUniqueString("^"); 1.2188 ++ return us; 1.2189 ++} 1.2190 ++ 1.2191 ++// "=" 1.2192 ++inline static const UniqueString* ustr__Zeq() { 1.2193 ++ static const UniqueString* us = NULL; 1.2194 ++ if (!us) us = ToUniqueString("="); 1.2195 ++ return us; 1.2196 ++} 1.2197 ++ 1.2198 ++// ".cfa" 1.2199 ++inline static const UniqueString* ustr__ZDcfa() { 1.2200 ++ static const UniqueString* us = NULL; 1.2201 ++ if (!us) us = ToUniqueString(".cfa"); 1.2202 ++ return us; 1.2203 ++} 1.2204 ++ 1.2205 ++// ".ra" 1.2206 ++inline static const UniqueString* ustr__ZDra() { 1.2207 ++ static const UniqueString* us = NULL; 1.2208 ++ if (!us) us = ToUniqueString(".ra"); 1.2209 ++ return us; 1.2210 ++} 1.2211 ++ 1.2212 ++} // namespace google_breakpad 1.2213 ++ 1.2214 ++#endif // COMMON_UNIQUE_STRING_H_ 1.2215 +diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc 1.2216 +--- a/src/processor/basic_source_line_resolver_unittest.cc 1.2217 ++++ b/src/processor/basic_source_line_resolver_unittest.cc 1.2218 +@@ -43,21 +43,30 @@ 1.2219 + #include "processor/windows_frame_info.h" 1.2220 + #include "processor/cfi_frame_info.h" 1.2221 + 1.2222 + namespace { 1.2223 + 1.2224 + using google_breakpad::BasicSourceLineResolver; 1.2225 + using google_breakpad::CFIFrameInfo; 1.2226 + using google_breakpad::CodeModule; 1.2227 ++using google_breakpad::FromUniqueString; 1.2228 + using google_breakpad::MemoryRegion; 1.2229 + using google_breakpad::StackFrame; 1.2230 ++using google_breakpad::ToUniqueString; 1.2231 + using google_breakpad::WindowsFrameInfo; 1.2232 + using google_breakpad::linked_ptr; 1.2233 + using google_breakpad::scoped_ptr; 1.2234 ++using google_breakpad::ustr__ZDcfa; 1.2235 ++using google_breakpad::ustr__ZDra; 1.2236 ++using google_breakpad::ustr__ZSebx; 1.2237 ++using google_breakpad::ustr__ZSebp; 1.2238 ++using google_breakpad::ustr__ZSedi; 1.2239 ++using google_breakpad::ustr__ZSesi; 1.2240 ++using google_breakpad::ustr__ZSesp; 1.2241 + 1.2242 + class TestCodeModule : public CodeModule { 1.2243 + public: 1.2244 + TestCodeModule(string code_file) : code_file_(code_file) {} 1.2245 + virtual ~TestCodeModule() {} 1.2246 + 1.2247 + virtual uint64_t base_address() const { return 0; } 1.2248 + virtual uint64_t size() const { return 0xb000; } 1.2249 +@@ -107,34 +116,34 @@ 1.2250 + // association. (That is, ACTUAL's associations should be a subset of 1.2251 + // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and 1.2252 + // ".cfa". 1.2253 + static bool VerifyRegisters( 1.2254 + const char *file, int line, 1.2255 + const CFIFrameInfo::RegisterValueMap<uint32_t> &expected, 1.2256 + const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) { 1.2257 + CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; 1.2258 +- a = actual.find(".cfa"); 1.2259 ++ a = actual.find(ustr__ZDcfa()); 1.2260 + if (a == actual.end()) 1.2261 + return false; 1.2262 +- a = actual.find(".ra"); 1.2263 ++ a = actual.find(ustr__ZDra()); 1.2264 + if (a == actual.end()) 1.2265 + return false; 1.2266 + for (a = actual.begin(); a != actual.end(); a++) { 1.2267 + CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = 1.2268 + expected.find(a->first); 1.2269 + if (e == expected.end()) { 1.2270 + fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", 1.2271 +- file, line, a->first.c_str(), a->second); 1.2272 ++ file, line, FromUniqueString(a->first), a->second); 1.2273 + return false; 1.2274 + } 1.2275 + if (e->second != a->second) { 1.2276 + fprintf(stderr, 1.2277 + "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", 1.2278 +- file, line, a->first.c_str(), a->second, e->second); 1.2279 ++ file, line, FromUniqueString(a->first), a->second, e->second); 1.2280 + return false; 1.2281 + } 1.2282 + // Don't complain if this doesn't recover all registers. Although 1.2283 + // the DWARF spec says that unmentioned registers are undefined, 1.2284 + // GCC uses omission to mean that they are unchanged. 1.2285 + } 1.2286 + return true; 1.2287 + } 1.2288 +@@ -254,81 +263,81 @@ 1.2289 + 1.2290 + CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; 1.2291 + CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; 1.2292 + CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; 1.2293 + MockMemoryRegion memory; 1.2294 + 1.2295 + // Regardless of which instruction evaluation takes place at, it 1.2296 + // should produce the same values for the caller's registers. 1.2297 +- expected_caller_registers[".cfa"] = 0x1001c; 1.2298 +- expected_caller_registers[".ra"] = 0xf6438648; 1.2299 +- expected_caller_registers["$ebp"] = 0x10038; 1.2300 +- expected_caller_registers["$ebx"] = 0x98ecadc3; 1.2301 +- expected_caller_registers["$esi"] = 0x878f7524; 1.2302 +- expected_caller_registers["$edi"] = 0x6312f9a5; 1.2303 ++ expected_caller_registers[ustr__ZDcfa()] = 0x1001c; 1.2304 ++ expected_caller_registers[ustr__ZDra()] = 0xf6438648; 1.2305 ++ expected_caller_registers[ustr__ZSebp()] = 0x10038; 1.2306 ++ expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3; 1.2307 ++ expected_caller_registers[ustr__ZSesi()] = 0x878f7524; 1.2308 ++ expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5; 1.2309 + 1.2310 + frame.instruction = 0x3d40; 1.2311 + frame.module = &module1; 1.2312 + current_registers.clear(); 1.2313 +- current_registers["$esp"] = 0x10018; 1.2314 +- current_registers["$ebp"] = 0x10038; 1.2315 +- current_registers["$ebx"] = 0x98ecadc3; 1.2316 +- current_registers["$esi"] = 0x878f7524; 1.2317 +- current_registers["$edi"] = 0x6312f9a5; 1.2318 ++ current_registers[ustr__ZSesp()] = 0x10018; 1.2319 ++ current_registers[ustr__ZSebp()] = 0x10038; 1.2320 ++ current_registers[ustr__ZSebx()] = 0x98ecadc3; 1.2321 ++ current_registers[ustr__ZSesi()] = 0x878f7524; 1.2322 ++ current_registers[ustr__ZSedi()] = 0x6312f9a5; 1.2323 + cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 1.2324 + ASSERT_TRUE(cfi_frame_info.get()); 1.2325 + ASSERT_TRUE(cfi_frame_info.get() 1.2326 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.2327 + &caller_registers)); 1.2328 + ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 1.2329 + expected_caller_registers, caller_registers)); 1.2330 + 1.2331 + frame.instruction = 0x3d41; 1.2332 +- current_registers["$esp"] = 0x10014; 1.2333 ++ current_registers[ustr__ZSesp()] = 0x10014; 1.2334 + cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 1.2335 + ASSERT_TRUE(cfi_frame_info.get()); 1.2336 + ASSERT_TRUE(cfi_frame_info.get() 1.2337 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.2338 + &caller_registers)); 1.2339 + ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 1.2340 + expected_caller_registers, caller_registers)); 1.2341 + 1.2342 + frame.instruction = 0x3d43; 1.2343 +- current_registers["$ebp"] = 0x10014; 1.2344 ++ current_registers[ustr__ZSebp()] = 0x10014; 1.2345 + cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 1.2346 + ASSERT_TRUE(cfi_frame_info.get()); 1.2347 + ASSERT_TRUE(cfi_frame_info.get() 1.2348 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.2349 + &caller_registers)); 1.2350 + VerifyRegisters(__FILE__, __LINE__, 1.2351 + expected_caller_registers, caller_registers); 1.2352 + 1.2353 + frame.instruction = 0x3d54; 1.2354 +- current_registers["$ebx"] = 0x6864f054U; 1.2355 ++ current_registers[ustr__ZSebx()] = 0x6864f054U; 1.2356 + cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 1.2357 + ASSERT_TRUE(cfi_frame_info.get()); 1.2358 + ASSERT_TRUE(cfi_frame_info.get() 1.2359 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.2360 + &caller_registers)); 1.2361 + VerifyRegisters(__FILE__, __LINE__, 1.2362 + expected_caller_registers, caller_registers); 1.2363 + 1.2364 + frame.instruction = 0x3d5a; 1.2365 +- current_registers["$esi"] = 0x6285f79aU; 1.2366 ++ current_registers[ustr__ZSesi()] = 0x6285f79aU; 1.2367 + cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 1.2368 + ASSERT_TRUE(cfi_frame_info.get()); 1.2369 + ASSERT_TRUE(cfi_frame_info.get() 1.2370 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.2371 + &caller_registers)); 1.2372 + VerifyRegisters(__FILE__, __LINE__, 1.2373 + expected_caller_registers, caller_registers); 1.2374 + 1.2375 + frame.instruction = 0x3d84; 1.2376 +- current_registers["$edi"] = 0x64061449U; 1.2377 ++ current_registers[ustr__ZSedi()] = 0x64061449U; 1.2378 + cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 1.2379 + ASSERT_TRUE(cfi_frame_info.get()); 1.2380 + ASSERT_TRUE(cfi_frame_info.get() 1.2381 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.2382 + &caller_registers)); 1.2383 + VerifyRegisters(__FILE__, __LINE__, 1.2384 + expected_caller_registers, caller_registers); 1.2385 + 1.2386 +diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc 1.2387 +--- a/src/processor/cfi_frame_info.cc 1.2388 ++++ b/src/processor/cfi_frame_info.cc 1.2389 +@@ -31,16 +31,17 @@ 1.2390 + 1.2391 + // cfi_frame_info.cc: Implementation of CFIFrameInfo class. 1.2392 + // See cfi_frame_info.h for details. 1.2393 + 1.2394 + #include "processor/cfi_frame_info.h" 1.2395 + 1.2396 + #include <string.h> 1.2397 + 1.2398 ++#include <algorithm> 1.2399 + #include <sstream> 1.2400 + 1.2401 + #include "common/scoped_ptr.h" 1.2402 + #include "processor/postfix_evaluator-inl.h" 1.2403 + 1.2404 + namespace google_breakpad { 1.2405 + 1.2406 + #ifdef _WIN32 1.2407 +@@ -65,33 +66,33 @@ 1.2408 + V cfa; 1.2409 + working = registers; 1.2410 + if (!evaluator.EvaluateForValue(cfa_rule_, &cfa)) 1.2411 + return false; 1.2412 + 1.2413 + // Then, compute the return address. 1.2414 + V ra; 1.2415 + working = registers; 1.2416 +- working[".cfa"] = cfa; 1.2417 ++ working[ustr__ZDcfa()] = cfa; 1.2418 + if (!evaluator.EvaluateForValue(ra_rule_, &ra)) 1.2419 + return false; 1.2420 + 1.2421 + // Now, compute values for all the registers register_rules_ mentions. 1.2422 + for (RuleMap::const_iterator it = register_rules_.begin(); 1.2423 + it != register_rules_.end(); it++) { 1.2424 + V value; 1.2425 + working = registers; 1.2426 +- working[".cfa"] = cfa; 1.2427 ++ working[ustr__ZDcfa()] = cfa; 1.2428 + if (!evaluator.EvaluateForValue(it->second, &value)) 1.2429 + return false; 1.2430 + (*caller_registers)[it->first] = value; 1.2431 + } 1.2432 + 1.2433 +- (*caller_registers)[".ra"] = ra; 1.2434 +- (*caller_registers)[".cfa"] = cfa; 1.2435 ++ (*caller_registers)[ustr__ZDra()] = ra; 1.2436 ++ (*caller_registers)[ustr__ZDcfa()] = cfa; 1.2437 + 1.2438 + return true; 1.2439 + } 1.2440 + 1.2441 + // Explicit instantiations for 32-bit and 64-bit architectures. 1.2442 + template bool CFIFrameInfo::FindCallerRegs<uint32_t>( 1.2443 + const RegisterValueMap<uint32_t> ®isters, 1.2444 + const MemoryRegion &memory, 1.2445 +@@ -107,81 +108,98 @@ 1.2446 + if (!cfa_rule_.invalid()) { 1.2447 + stream << ".cfa: " << cfa_rule_; 1.2448 + } 1.2449 + if (!ra_rule_.invalid()) { 1.2450 + if (static_cast<std::streamoff>(stream.tellp()) != 0) 1.2451 + stream << " "; 1.2452 + stream << ".ra: " << ra_rule_; 1.2453 + } 1.2454 ++ 1.2455 ++ // Visit the register rules in alphabetical order. Because 1.2456 ++ // register_rules_ has the elements in some arbitrary order, 1.2457 ++ // get the names out into a vector, sort them, and visit in 1.2458 ++ // sorted order. 1.2459 ++ std::vector<const UniqueString*> rr_names; 1.2460 + for (RuleMap::const_iterator iter = register_rules_.begin(); 1.2461 + iter != register_rules_.end(); 1.2462 + ++iter) { 1.2463 ++ rr_names.push_back(iter->first); 1.2464 ++ } 1.2465 ++ 1.2466 ++ std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString); 1.2467 ++ 1.2468 ++ // Now visit the register rules in alphabetical order. 1.2469 ++ for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin(); 1.2470 ++ name != rr_names.end(); 1.2471 ++ ++name) { 1.2472 ++ const UniqueString* nm = *name; 1.2473 ++ Module::Expr rule = register_rules_.find(nm)->second; 1.2474 + if (static_cast<std::streamoff>(stream.tellp()) != 0) 1.2475 + stream << " "; 1.2476 +- stream << iter->first << ": " << iter->second; 1.2477 ++ stream << FromUniqueString(nm) << ": " << rule; 1.2478 + } 1.2479 + 1.2480 + return stream.str(); 1.2481 + } 1.2482 + 1.2483 + bool CFIRuleParser::Parse(const string &rule_set) { 1.2484 + size_t rule_set_len = rule_set.size(); 1.2485 + scoped_array<char> working_copy(new char[rule_set_len + 1]); 1.2486 + memcpy(working_copy.get(), rule_set.data(), rule_set_len); 1.2487 + working_copy[rule_set_len] = '\0'; 1.2488 + 1.2489 +- name_.clear(); 1.2490 ++ name_ = ustr__empty(); 1.2491 + expression_.clear(); 1.2492 + 1.2493 + char *cursor; 1.2494 + static const char token_breaks[] = " \t\r\n"; 1.2495 + char *token = strtok_r(working_copy.get(), token_breaks, &cursor); 1.2496 + 1.2497 + for (;;) { 1.2498 + // End of rule set? 1.2499 + if (!token) return Report(); 1.2500 + 1.2501 + // Register/pseudoregister name? 1.2502 + size_t token_len = strlen(token); 1.2503 + if (token_len >= 1 && token[token_len - 1] == ':') { 1.2504 + // Names can't be empty. 1.2505 + if (token_len < 2) return false; 1.2506 + // If there is any pending content, report it. 1.2507 +- if (!name_.empty() || !expression_.empty()) { 1.2508 ++ if (name_ != ustr__empty() || !expression_.empty()) { 1.2509 + if (!Report()) return false; 1.2510 + } 1.2511 +- name_.assign(token, token_len - 1); 1.2512 ++ name_ = ToUniqueString_n(token, token_len - 1); 1.2513 + expression_.clear(); 1.2514 + } else { 1.2515 + // Another expression component. 1.2516 + assert(token_len > 0); // strtok_r guarantees this, I think. 1.2517 + if (!expression_.empty()) 1.2518 + expression_ += ' '; 1.2519 + expression_ += token; 1.2520 + } 1.2521 + token = strtok_r(NULL, token_breaks, &cursor); 1.2522 + } 1.2523 + } 1.2524 + 1.2525 + bool CFIRuleParser::Report() { 1.2526 +- if (name_.empty() || expression_.empty()) return false; 1.2527 +- if (name_ == ".cfa") handler_->CFARule(expression_); 1.2528 +- else if (name_ == ".ra") handler_->RARule(expression_); 1.2529 ++ if (name_ == ustr__empty() || expression_.empty()) return false; 1.2530 ++ if (name_ == ustr__ZDcfa()) handler_->CFARule(expression_); 1.2531 ++ else if (name_ == ustr__ZDra()) handler_->RARule(expression_); 1.2532 + else handler_->RegisterRule(name_, expression_); 1.2533 + return true; 1.2534 + } 1.2535 + 1.2536 + void CFIFrameInfoParseHandler::CFARule(const string &expression) { 1.2537 + // 'expression' is a postfix expression string. 1.2538 + frame_info_->SetCFARule(Module::Expr(expression)); 1.2539 + } 1.2540 + 1.2541 + void CFIFrameInfoParseHandler::RARule(const string &expression) { 1.2542 + frame_info_->SetRARule(Module::Expr(expression)); 1.2543 + } 1.2544 + 1.2545 +-void CFIFrameInfoParseHandler::RegisterRule(const string &name, 1.2546 ++void CFIFrameInfoParseHandler::RegisterRule(const UniqueString* name, 1.2547 + const string &expression) { 1.2548 + frame_info_->SetRegisterRule(name, Module::Expr(expression)); 1.2549 + } 1.2550 + 1.2551 + } // namespace google_breakpad 1.2552 +diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h 1.2553 +--- a/src/processor/cfi_frame_info.h 1.2554 ++++ b/src/processor/cfi_frame_info.h 1.2555 +@@ -37,16 +37,17 @@ 1.2556 + 1.2557 + #ifndef PROCESSOR_CFI_FRAME_INFO_H_ 1.2558 + #define PROCESSOR_CFI_FRAME_INFO_H_ 1.2559 + 1.2560 + #include <map> 1.2561 + #include <string> 1.2562 + 1.2563 + #include "common/using_std_string.h" 1.2564 ++#include "common/unique_string.h" 1.2565 + #include "google_breakpad/common/breakpad_types.h" 1.2566 + #include "common/module.h" 1.2567 + 1.2568 + namespace google_breakpad { 1.2569 + 1.2570 + using std::map; 1.2571 + 1.2572 + class MemoryRegion; 1.2573 +@@ -63,24 +64,24 @@ 1.2574 + // changes given by the 'STACK CFI' records up to our instruction's 1.2575 + // address. Then, use the FindCallerRegs member function to apply the 1.2576 + // rules to the callee frame's register values, yielding the caller 1.2577 + // frame's register values. 1.2578 + class CFIFrameInfo { 1.2579 + public: 1.2580 + // A map from register names onto values. 1.2581 + template<typename ValueType> class RegisterValueMap: 1.2582 +- public map<string, ValueType> { }; 1.2583 ++ public map<const UniqueString*, ValueType> { }; 1.2584 + 1.2585 + // Set the expression for computing a call frame address, return 1.2586 + // address, or register's value. At least the CFA rule and the RA 1.2587 + // rule must be set before calling FindCallerRegs. 1.2588 + void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; } 1.2589 + void SetRARule(const Module::Expr& rule) { ra_rule_ = rule; } 1.2590 +- void SetRegisterRule(const string& register_name, 1.2591 ++ void SetRegisterRule(const UniqueString* register_name, 1.2592 + const Module::Expr& rule) { 1.2593 + register_rules_[register_name] = rule; 1.2594 + } 1.2595 + 1.2596 + // Compute the values of the calling frame's registers, according to 1.2597 + // this rule set. Use ValueType in expression evaluation; this 1.2598 + // should be uint32_t on machines with 32-bit addresses, or 1.2599 + // uint64_t on machines with 64-bit addresses. 1.2600 +@@ -104,17 +105,17 @@ 1.2601 + 1.2602 + // Serialize the rules in this object into a string in the format 1.2603 + // of STACK CFI records. 1.2604 + string Serialize() const; 1.2605 + 1.2606 + private: 1.2607 + 1.2608 + // A map from register names onto evaluation rules. 1.2609 +- typedef map<string, Module::Expr> RuleMap; 1.2610 ++ typedef map<const UniqueString*, Module::Expr> RuleMap; 1.2611 + 1.2612 + // An expression for computing the current frame's CFA (call 1.2613 + // frame address). The CFA is a reference address for the frame that 1.2614 + // remains unchanged throughout the frame's lifetime. You should 1.2615 + // evaluate this expression with a dictionary initially populated 1.2616 + // with the values of the current frame's known registers. 1.2617 + Module::Expr cfa_rule_; 1.2618 + 1.2619 +@@ -145,17 +146,18 @@ 1.2620 + Handler() { } 1.2621 + virtual ~Handler() { } 1.2622 + 1.2623 + // The input specifies EXPRESSION as the CFA/RA computation rule. 1.2624 + virtual void CFARule(const string &expression) = 0; 1.2625 + virtual void RARule(const string &expression) = 0; 1.2626 + 1.2627 + // The input specifies EXPRESSION as the recovery rule for register NAME. 1.2628 +- virtual void RegisterRule(const string &name, const string &expression) = 0; 1.2629 ++ virtual void RegisterRule(const UniqueString* name, 1.2630 ++ const string &expression) = 0; 1.2631 + }; 1.2632 + 1.2633 + // Construct a parser which feeds its results to HANDLER. 1.2634 + CFIRuleParser(Handler *handler) : handler_(handler) { } 1.2635 + 1.2636 + // Parse RULE_SET as a set of CFA computation and RA/register 1.2637 + // recovery rules, as appearing in STACK CFI records. Report the 1.2638 + // results of parsing by making the appropriate calls to handler_. 1.2639 +@@ -165,30 +167,31 @@ 1.2640 + private: 1.2641 + // Report any accumulated rule to handler_ 1.2642 + bool Report(); 1.2643 + 1.2644 + // The handler to which the parser reports its findings. 1.2645 + Handler *handler_; 1.2646 + 1.2647 + // Working data. 1.2648 +- string name_, expression_; 1.2649 ++ const UniqueString* name_; 1.2650 ++ string expression_; 1.2651 + }; 1.2652 + 1.2653 + // A handler for rule set parsing that populates a CFIFrameInfo with 1.2654 + // the results. 1.2655 + class CFIFrameInfoParseHandler: public CFIRuleParser::Handler { 1.2656 + public: 1.2657 + // Populate FRAME_INFO with the results of parsing. 1.2658 + CFIFrameInfoParseHandler(CFIFrameInfo *frame_info) 1.2659 + : frame_info_(frame_info) { } 1.2660 + 1.2661 + void CFARule(const string &expression); 1.2662 + void RARule(const string &expression); 1.2663 +- void RegisterRule(const string &name, const string &expression); 1.2664 ++ void RegisterRule(const UniqueString* name, const string &expression); 1.2665 + 1.2666 + private: 1.2667 + CFIFrameInfo *frame_info_; 1.2668 + }; 1.2669 + 1.2670 + // A utility class template for simple 'STACK CFI'-driven stack walkers. 1.2671 + // Given a CFIFrameInfo instance, a table describing the architecture's 1.2672 + // register set, and a context holding the last frame's registers, an 1.2673 +@@ -205,24 +208,24 @@ 1.2674 + // uint32_t or uint64_t. RawContextType should be the raw context 1.2675 + // structure type for this architecture. 1.2676 + template <typename RegisterType, class RawContextType> 1.2677 + class SimpleCFIWalker { 1.2678 + public: 1.2679 + // A structure describing one architecture register. 1.2680 + struct RegisterSet { 1.2681 + // The register name, as it appears in STACK CFI rules. 1.2682 +- const char *name; 1.2683 ++ const UniqueString* name; 1.2684 + 1.2685 + // An alternate name that the register's value might be found 1.2686 + // under in a register value dictionary, or NULL. When generating 1.2687 + // names, prefer NAME to this value. It's common to list ".cfa" as 1.2688 + // an alternative name for the stack pointer, and ".ra" as an 1.2689 + // alternative name for the instruction pointer. 1.2690 +- const char *alternate_name; 1.2691 ++ const UniqueString* alternate_name; 1.2692 + 1.2693 + // True if the callee is expected to preserve the value of this 1.2694 + // register. If this flag is true for some register R, and the STACK 1.2695 + // CFI records provide no rule to recover R, then SimpleCFIWalker 1.2696 + // assumes that the callee has not changed R's value, and the caller's 1.2697 + // value for R is that currently in the callee's context. 1.2698 + bool callee_saves; 1.2699 + 1.2700 +diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc 1.2701 +--- a/src/processor/cfi_frame_info_unittest.cc 1.2702 ++++ b/src/processor/cfi_frame_info_unittest.cc 1.2703 +@@ -38,19 +38,24 @@ 1.2704 + #include "common/module.h" 1.2705 + #include "common/using_std_string.h" 1.2706 + #include "processor/cfi_frame_info.h" 1.2707 + #include "google_breakpad/processor/memory_region.h" 1.2708 + 1.2709 + using google_breakpad::CFIFrameInfo; 1.2710 + using google_breakpad::CFIFrameInfoParseHandler; 1.2711 + using google_breakpad::CFIRuleParser; 1.2712 ++using google_breakpad::FromUniqueString; 1.2713 + using google_breakpad::MemoryRegion; 1.2714 + using google_breakpad::Module; 1.2715 + using google_breakpad::SimpleCFIWalker; 1.2716 ++using google_breakpad::ToUniqueString; 1.2717 ++using google_breakpad::UniqueString; 1.2718 ++using google_breakpad::ustr__ZDcfa; 1.2719 ++using google_breakpad::ustr__ZDra; 1.2720 + using testing::_; 1.2721 + using testing::A; 1.2722 + using testing::AtMost; 1.2723 + using testing::DoAll; 1.2724 + using testing::Return; 1.2725 + using testing::SetArgumentPointee; 1.2726 + using testing::Test; 1.2727 + 1.2728 +@@ -107,41 +112,47 @@ 1.2729 + TEST_F(Simple, SetCFAAndRARule) { 1.2730 + ExpectNoMemoryReferences(); 1.2731 + 1.2732 + cfi.SetCFARule(Module::Expr("330903416631436410")); 1.2733 + cfi.SetRARule(Module::Expr("5870666104170902211")); 1.2734 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2735 + &caller_registers)); 1.2736 + ASSERT_EQ(2U, caller_registers.size()); 1.2737 +- ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]); 1.2738 +- ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]); 1.2739 ++ ASSERT_EQ(330903416631436410ULL, caller_registers[ustr__ZDcfa()]); 1.2740 ++ ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]); 1.2741 + 1.2742 + ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211", 1.2743 + cfi.Serialize()); 1.2744 + } 1.2745 + 1.2746 + TEST_F(Simple, SetManyRules) { 1.2747 + ExpectNoMemoryReferences(); 1.2748 + 1.2749 + cfi.SetCFARule(Module::Expr("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -")); 1.2750 + cfi.SetRARule(Module::Expr(".cfa 99804755 +")); 1.2751 +- cfi.SetRegisterRule("register1", Module::Expr(".cfa 54370437 *")); 1.2752 +- cfi.SetRegisterRule("vodkathumbscrewingly", Module::Expr("24076308 .cfa +")); 1.2753 +- cfi.SetRegisterRule("pubvexingfjordschmaltzy", Module::Expr(".cfa 29801007 -")); 1.2754 +- cfi.SetRegisterRule("uncopyrightables", Module::Expr("92642917 .cfa /")); 1.2755 ++ 1.2756 ++ const UniqueString* reg1 = ToUniqueString("register1"); 1.2757 ++ const UniqueString* reg2 = ToUniqueString("vodkathumbscrewingly"); 1.2758 ++ const UniqueString* reg3 = ToUniqueString("pubvexingfjordschmaltzy"); 1.2759 ++ const UniqueString* reg4 = ToUniqueString("uncopyrightables"); 1.2760 ++ 1.2761 ++ cfi.SetRegisterRule(reg1, Module::Expr(".cfa 54370437 *")); 1.2762 ++ cfi.SetRegisterRule(reg2, Module::Expr("24076308 .cfa +")); 1.2763 ++ cfi.SetRegisterRule(reg3, Module::Expr(".cfa 29801007 -")); 1.2764 ++ cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /")); 1.2765 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2766 + &caller_registers)); 1.2767 + ASSERT_EQ(6U, caller_registers.size()); 1.2768 +- ASSERT_EQ(7664691U, caller_registers[".cfa"]); 1.2769 +- ASSERT_EQ(107469446U, caller_registers[".ra"]); 1.2770 +- ASSERT_EQ(416732599139967ULL, caller_registers["register1"]); 1.2771 +- ASSERT_EQ(31740999U, caller_registers["vodkathumbscrewingly"]); 1.2772 +- ASSERT_EQ(-22136316ULL, caller_registers["pubvexingfjordschmaltzy"]); 1.2773 +- ASSERT_EQ(12U, caller_registers["uncopyrightables"]); 1.2774 ++ ASSERT_EQ(7664691U, caller_registers[ustr__ZDcfa()]); 1.2775 ++ ASSERT_EQ(107469446U, caller_registers[ustr__ZDra()]); 1.2776 ++ ASSERT_EQ(416732599139967ULL, caller_registers[reg1]); 1.2777 ++ ASSERT_EQ(31740999U, caller_registers[reg2]); 1.2778 ++ ASSERT_EQ(-22136316ULL, caller_registers[reg3]); 1.2779 ++ ASSERT_EQ(12U, caller_registers[reg4]); 1.2780 + ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - " 1.2781 + ".ra: .cfa 99804755 + " 1.2782 + "pubvexingfjordschmaltzy: .cfa 29801007 - " 1.2783 + "register1: .cfa 54370437 * " 1.2784 + "uncopyrightables: 92642917 .cfa / " 1.2785 + "vodkathumbscrewingly: 24076308 .cfa +", 1.2786 + cfi.Serialize()); 1.2787 + } 1.2788 +@@ -150,18 +161,18 @@ 1.2789 + ExpectNoMemoryReferences(); 1.2790 + 1.2791 + cfi.SetCFARule(Module::Expr("330903416631436410")); 1.2792 + cfi.SetRARule(Module::Expr("5870666104170902211")); 1.2793 + cfi.SetCFARule(Module::Expr("2828089117179001")); 1.2794 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2795 + &caller_registers)); 1.2796 + ASSERT_EQ(2U, caller_registers.size()); 1.2797 +- ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]); 1.2798 +- ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]); 1.2799 ++ ASSERT_EQ(2828089117179001ULL, caller_registers[ustr__ZDcfa()]); 1.2800 ++ ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]); 1.2801 + ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211", 1.2802 + cfi.Serialize()); 1.2803 + } 1.2804 + 1.2805 + class Scope: public CFIFixture, public Test { }; 1.2806 + 1.2807 + // There should be no value for .cfa in scope when evaluating the CFA rule. 1.2808 + TEST_F(Scope, CFALacksCFA) { 1.2809 +@@ -183,37 +194,39 @@ 1.2810 + &caller_registers)); 1.2811 + } 1.2812 + 1.2813 + // The current frame's registers should be in scope when evaluating 1.2814 + // the CFA rule. 1.2815 + TEST_F(Scope, CFASeesCurrentRegs) { 1.2816 + ExpectNoMemoryReferences(); 1.2817 + 1.2818 +- registers[".baraminology"] = 0x06a7bc63e4f13893ULL; 1.2819 +- registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL; 1.2820 ++ const UniqueString* reg1 = ToUniqueString(".baraminology"); 1.2821 ++ const UniqueString* reg2 = ToUniqueString(".ornithorhynchus"); 1.2822 ++ registers[reg1] = 0x06a7bc63e4f13893ULL; 1.2823 ++ registers[reg2] = 0x5e0bf850bafce9d2ULL; 1.2824 + cfi.SetCFARule(Module::Expr(".baraminology .ornithorhynchus +")); 1.2825 + cfi.SetRARule(Module::Expr("0")); 1.2826 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2827 + &caller_registers)); 1.2828 + ASSERT_EQ(2U, caller_registers.size()); 1.2829 + ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL, 1.2830 +- caller_registers[".cfa"]); 1.2831 ++ caller_registers[ustr__ZDcfa()]); 1.2832 + } 1.2833 + 1.2834 + // .cfa should be in scope in the return address expression. 1.2835 + TEST_F(Scope, RASeesCFA) { 1.2836 + ExpectNoMemoryReferences(); 1.2837 + 1.2838 + cfi.SetCFARule(Module::Expr("48364076")); 1.2839 + cfi.SetRARule(Module::Expr(".cfa")); 1.2840 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2841 + &caller_registers)); 1.2842 + ASSERT_EQ(2U, caller_registers.size()); 1.2843 +- ASSERT_EQ(48364076U, caller_registers[".ra"]); 1.2844 ++ ASSERT_EQ(48364076U, caller_registers[ustr__ZDra()]); 1.2845 + } 1.2846 + 1.2847 + // There should be no value for .ra in scope when evaluating the CFA rule. 1.2848 + TEST_F(Scope, RALacksRA) { 1.2849 + ExpectNoMemoryReferences(); 1.2850 + 1.2851 + cfi.SetCFARule(Module::Expr("0")); 1.2852 + cfi.SetRARule(Module::Expr(".ra")); 1.2853 +@@ -221,64 +234,69 @@ 1.2854 + &caller_registers)); 1.2855 + } 1.2856 + 1.2857 + // The current frame's registers should be in scope in the return 1.2858 + // address expression. 1.2859 + TEST_F(Scope, RASeesCurrentRegs) { 1.2860 + ExpectNoMemoryReferences(); 1.2861 + 1.2862 +- registers["noachian"] = 0x54dc4a5d8e5eb503ULL; 1.2863 + cfi.SetCFARule(Module::Expr("10359370")); 1.2864 +- cfi.SetRARule(Module::Expr("noachian")); 1.2865 ++ const UniqueString* reg1 = ToUniqueString("noachian"); 1.2866 ++ registers[reg1] = 0x54dc4a5d8e5eb503ULL; 1.2867 ++ cfi.SetRARule(Module::Expr(reg1, 0, false)); 1.2868 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2869 + &caller_registers)); 1.2870 + ASSERT_EQ(2U, caller_registers.size()); 1.2871 +- ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]); 1.2872 ++ ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[ustr__ZDra()]); 1.2873 + } 1.2874 + 1.2875 + // .cfa should be in scope for register rules. 1.2876 + TEST_F(Scope, RegistersSeeCFA) { 1.2877 + ExpectNoMemoryReferences(); 1.2878 + 1.2879 + cfi.SetCFARule(Module::Expr("6515179")); 1.2880 + cfi.SetRARule(Module::Expr(".cfa")); 1.2881 +- cfi.SetRegisterRule("rogerian", Module::Expr(".cfa")); 1.2882 ++ const UniqueString* reg1 = ToUniqueString("rogerian"); 1.2883 ++ cfi.SetRegisterRule(reg1, Module::Expr(".cfa")); 1.2884 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2885 + &caller_registers)); 1.2886 + ASSERT_EQ(3U, caller_registers.size()); 1.2887 +- ASSERT_EQ(6515179U, caller_registers["rogerian"]); 1.2888 ++ ASSERT_EQ(6515179U, caller_registers[reg1]); 1.2889 + } 1.2890 + 1.2891 + // The return address should not be in scope for register rules. 1.2892 + TEST_F(Scope, RegsLackRA) { 1.2893 + ExpectNoMemoryReferences(); 1.2894 + 1.2895 + cfi.SetCFARule(Module::Expr("42740329")); 1.2896 + cfi.SetRARule(Module::Expr("27045204")); 1.2897 +- cfi.SetRegisterRule("$r1", Module::Expr(".ra")); 1.2898 ++ const UniqueString* reg1 = ToUniqueString("$r1"); 1.2899 ++ cfi.SetRegisterRule(reg1, Module::Expr(".ra")); 1.2900 + ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2901 + &caller_registers)); 1.2902 + } 1.2903 + 1.2904 + // Register rules can see the current frame's register values. 1.2905 + TEST_F(Scope, RegsSeeRegs) { 1.2906 + ExpectNoMemoryReferences(); 1.2907 + 1.2908 +- registers["$r1"] = 0x6ed3582c4bedb9adULL; 1.2909 +- registers["$r2"] = 0xd27d9e742b8df6d0ULL; 1.2910 ++ const UniqueString* reg1 = ToUniqueString("$r1"); 1.2911 ++ const UniqueString* reg2 = ToUniqueString("$r2"); 1.2912 ++ registers[reg1] = 0x6ed3582c4bedb9adULL; 1.2913 ++ registers[reg2] = 0xd27d9e742b8df6d0ULL; 1.2914 + cfi.SetCFARule(Module::Expr("88239303")); 1.2915 + cfi.SetRARule(Module::Expr("30503835")); 1.2916 +- cfi.SetRegisterRule("$r1", Module::Expr("$r1 42175211 = $r2")); 1.2917 +- cfi.SetRegisterRule("$r2", Module::Expr("$r2 21357221 = $r1")); 1.2918 ++ cfi.SetRegisterRule(reg1, Module::Expr("$r1 42175211 = $r2")); 1.2919 ++ cfi.SetRegisterRule(reg2, Module::Expr("$r2 21357221 = $r1")); 1.2920 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2921 + &caller_registers)); 1.2922 + ASSERT_EQ(4U, caller_registers.size()); 1.2923 +- ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]); 1.2924 +- ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]); 1.2925 ++ ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers[reg1]); 1.2926 ++ ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers[reg2]); 1.2927 + } 1.2928 + 1.2929 + // Each rule's temporaries are separate. 1.2930 + TEST_F(Scope, SeparateTempsRA) { 1.2931 + ExpectNoMemoryReferences(); 1.2932 + 1.2933 + cfi.SetCFARule(Module::Expr("$temp1 76569129 = $temp1")); 1.2934 + cfi.SetRARule(Module::Expr("0")); 1.2935 +@@ -290,17 +308,17 @@ 1.2936 + ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.2937 + &caller_registers)); 1.2938 + } 1.2939 + 1.2940 + class MockCFIRuleParserHandler: public CFIRuleParser::Handler { 1.2941 + public: 1.2942 + MOCK_METHOD1(CFARule, void(const string &)); 1.2943 + MOCK_METHOD1(RARule, void(const string &)); 1.2944 +- MOCK_METHOD2(RegisterRule, void(const string &, const string &)); 1.2945 ++ MOCK_METHOD2(RegisterRule, void(const UniqueString*, const string &)); 1.2946 + }; 1.2947 + 1.2948 + // A fixture class for testing CFIRuleParser. 1.2949 + class CFIParserFixture { 1.2950 + public: 1.2951 + CFIParserFixture() : parser(&mock_handler) { 1.2952 + // Expect no parsing results to be reported to mock_handler. Individual 1.2953 + // tests can override this. 1.2954 +@@ -361,100 +379,100 @@ 1.2955 + } 1.2956 + 1.2957 + TEST_F(Parser, RA) { 1.2958 + EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return()); 1.2959 + EXPECT_TRUE(parser.Parse(".ra: notoriety")); 1.2960 + } 1.2961 + 1.2962 + TEST_F(Parser, Reg) { 1.2963 +- EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous")) 1.2964 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("nemo"), "mellifluous")) 1.2965 + .WillOnce(Return()); 1.2966 + EXPECT_TRUE(parser.Parse("nemo: mellifluous")); 1.2967 + } 1.2968 + 1.2969 + TEST_F(Parser, CFARARegs) { 1.2970 + EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return()); 1.2971 + EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return()); 1.2972 +- EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian")) 1.2973 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("galba"), "praetorian")) 1.2974 + .WillOnce(Return()); 1.2975 +- EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius")) 1.2976 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("otho"), "vitellius")) 1.2977 + .WillOnce(Return()); 1.2978 + EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression " 1.2979 + "galba: praetorian otho: vitellius")); 1.2980 + } 1.2981 + 1.2982 + TEST_F(Parser, Whitespace) { 1.2983 +- EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression")) 1.2984 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "r1 expression")) 1.2985 + .WillOnce(Return()); 1.2986 +- EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression")) 1.2987 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r2"), "r2 expression")) 1.2988 + .WillOnce(Return()); 1.2989 + EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n " 1.2990 + "expression \n")); 1.2991 + } 1.2992 + 1.2993 + TEST_F(Parser, WhitespaceLoneColon) { 1.2994 + EXPECT_FALSE(parser.Parse(" \n:\t ")); 1.2995 + } 1.2996 + 1.2997 + TEST_F(Parser, EmptyName) { 1.2998 +- EXPECT_CALL(mock_handler, RegisterRule("reg", _)) 1.2999 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("reg"), _)) 1.3000 + .Times(AtMost(1)) 1.3001 + .WillRepeatedly(Return()); 1.3002 + EXPECT_FALSE(parser.Parse("reg: expr1 : expr2")); 1.3003 + } 1.3004 + 1.3005 + TEST_F(Parser, RuleLoneColon) { 1.3006 +- EXPECT_CALL(mock_handler, RegisterRule("r1", "expr")) 1.3007 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "expr")) 1.3008 + .Times(AtMost(1)) 1.3009 + .WillRepeatedly(Return()); 1.3010 + EXPECT_FALSE(parser.Parse(" r1: expr :")); 1.3011 + } 1.3012 + 1.3013 + TEST_F(Parser, RegNoExprRule) { 1.3014 +- EXPECT_CALL(mock_handler, RegisterRule("r1", "expr")) 1.3015 ++ EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "expr")) 1.3016 + .Times(AtMost(1)) 1.3017 + .WillRepeatedly(Return()); 1.3018 + EXPECT_FALSE(parser.Parse("r0: r1: expr")); 1.3019 + } 1.3020 + 1.3021 + class ParseHandlerFixture: public CFIFixture { 1.3022 + public: 1.3023 + ParseHandlerFixture() : CFIFixture(), handler(&cfi) { } 1.3024 + CFIFrameInfoParseHandler handler; 1.3025 + }; 1.3026 + 1.3027 + class ParseHandler: public ParseHandlerFixture, public Test { }; 1.3028 + 1.3029 + TEST_F(ParseHandler, CFARARule) { 1.3030 + handler.CFARule("reg-for-cfa"); 1.3031 + handler.RARule("reg-for-ra"); 1.3032 +- registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL; 1.3033 +- registers["reg-for-ra"] = 0x6301b475b8b91c02ULL; 1.3034 ++ registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL; 1.3035 ++ registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL; 1.3036 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.3037 + &caller_registers)); 1.3038 +- ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]); 1.3039 +- ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]); 1.3040 ++ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]); 1.3041 ++ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]); 1.3042 + } 1.3043 + 1.3044 + TEST_F(ParseHandler, RegisterRules) { 1.3045 + handler.CFARule("reg-for-cfa"); 1.3046 + handler.RARule("reg-for-ra"); 1.3047 +- handler.RegisterRule("reg1", "reg-for-reg1"); 1.3048 +- handler.RegisterRule("reg2", "reg-for-reg2"); 1.3049 +- registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL; 1.3050 +- registers["reg-for-ra"] = 0x6301b475b8b91c02ULL; 1.3051 +- registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL; 1.3052 +- registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL; 1.3053 ++ handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1"); 1.3054 ++ handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2"); 1.3055 ++ registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL; 1.3056 ++ registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL; 1.3057 ++ registers[ToUniqueString("reg-for-reg1")] = 0x06cde8e2ff062481ULL; 1.3058 ++ registers[ToUniqueString("reg-for-reg2")] = 0xff0c4f76403173e2ULL; 1.3059 + ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1.3060 + &caller_registers)); 1.3061 +- ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]); 1.3062 +- ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]); 1.3063 +- ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]); 1.3064 +- ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]); 1.3065 ++ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]); 1.3066 ++ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]); 1.3067 ++ ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers[ToUniqueString("reg1")]); 1.3068 ++ ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers[ToUniqueString("reg2")]); 1.3069 + } 1.3070 + 1.3071 + struct SimpleCFIWalkerFixture { 1.3072 + struct RawContext { 1.3073 + uint64_t r0, r1, r2, r3, r4, sp, pc; 1.3074 + }; 1.3075 + enum Validity { 1.3076 + R0_VALID = 0x01, 1.3077 +@@ -475,23 +493,23 @@ 1.3078 + CFIFrameInfo call_frame_info; 1.3079 + CFIWalker walker; 1.3080 + MockMemoryRegion memory; 1.3081 + RawContext callee_context, caller_context; 1.3082 + }; 1.3083 + 1.3084 + SimpleCFIWalkerFixture::CFIWalker::RegisterSet 1.3085 + SimpleCFIWalkerFixture::register_map[7] = { 1.3086 +- { "r0", NULL, true, R0_VALID, &RawContext::r0 }, 1.3087 +- { "r1", NULL, true, R1_VALID, &RawContext::r1 }, 1.3088 +- { "r2", NULL, false, R2_VALID, &RawContext::r2 }, 1.3089 +- { "r3", NULL, false, R3_VALID, &RawContext::r3 }, 1.3090 +- { "r4", NULL, true, R4_VALID, &RawContext::r4 }, 1.3091 +- { "sp", ".cfa", true, SP_VALID, &RawContext::sp }, 1.3092 +- { "pc", ".ra", true, PC_VALID, &RawContext::pc }, 1.3093 ++ { ToUniqueString("r0"), NULL, true, R0_VALID, &RawContext::r0 }, 1.3094 ++ { ToUniqueString("r1"), NULL, true, R1_VALID, &RawContext::r1 }, 1.3095 ++ { ToUniqueString("r2"), NULL, false, R2_VALID, &RawContext::r2 }, 1.3096 ++ { ToUniqueString("r3"), NULL, false, R3_VALID, &RawContext::r3 }, 1.3097 ++ { ToUniqueString("r4"), NULL, true, R4_VALID, &RawContext::r4 }, 1.3098 ++ { ToUniqueString("sp"), ustr__ZDcfa(), true, SP_VALID, &RawContext::sp }, 1.3099 ++ { ToUniqueString("pc"), ustr__ZDra(), true, PC_VALID, &RawContext::pc }, 1.3100 + }; 1.3101 + 1.3102 + class SimpleWalker: public SimpleCFIWalkerFixture, public Test { }; 1.3103 + 1.3104 + TEST_F(SimpleWalker, Walk) { 1.3105 + // Stack_top is the current stack pointer, pointing to the lowest 1.3106 + // address of a frame that looks like this (all 64-bit words): 1.3107 + // 1.3108 +@@ -516,18 +534,20 @@ 1.3109 + // Saved return address. 1.3110 + EXPECT_CALL(memory, 1.3111 + GetMemoryAtAddress(stack_top + 16, A<uint64_t *>())) 1.3112 + .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL), 1.3113 + Return(true))); 1.3114 + 1.3115 + call_frame_info.SetCFARule(Module::Expr("sp 24 +")); 1.3116 + call_frame_info.SetRARule(Module::Expr(".cfa 8 - ^")); 1.3117 +- call_frame_info.SetRegisterRule("r0", Module::Expr(".cfa 24 - ^")); 1.3118 +- call_frame_info.SetRegisterRule("r1", Module::Expr("r2")); 1.3119 ++ call_frame_info.SetRegisterRule(ToUniqueString("r0"), 1.3120 ++ Module::Expr(".cfa 24 - ^")); 1.3121 ++ call_frame_info.SetRegisterRule(ToUniqueString("r1"), 1.3122 ++ Module::Expr("r2")); 1.3123 + 1.3124 + callee_context.r0 = 0x94e030ca79edd119ULL; 1.3125 + callee_context.r1 = 0x937b4d7e95ce52d9ULL; 1.3126 + callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1 1.3127 + // callee_context.r3 is not valid in callee. 1.3128 + // callee_context.r4 is not valid in callee. 1.3129 + callee_context.sp = stack_top; 1.3130 + callee_context.pc = 0x25b21b224311d280ULL; 1.3131 +diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc 1.3132 +--- a/src/processor/fast_source_line_resolver_unittest.cc 1.3133 ++++ b/src/processor/fast_source_line_resolver_unittest.cc 1.3134 +@@ -51,25 +51,34 @@ 1.3135 + #include "processor/module_serializer.h" 1.3136 + #include "processor/module_comparer.h" 1.3137 + 1.3138 + namespace { 1.3139 + 1.3140 + using google_breakpad::SourceLineResolverBase; 1.3141 + using google_breakpad::BasicSourceLineResolver; 1.3142 + using google_breakpad::FastSourceLineResolver; 1.3143 ++using google_breakpad::FromUniqueString; 1.3144 + using google_breakpad::ModuleSerializer; 1.3145 + using google_breakpad::ModuleComparer; 1.3146 + using google_breakpad::CFIFrameInfo; 1.3147 + using google_breakpad::CodeModule; 1.3148 + using google_breakpad::MemoryRegion; 1.3149 + using google_breakpad::StackFrame; 1.3150 ++using google_breakpad::ToUniqueString; 1.3151 + using google_breakpad::WindowsFrameInfo; 1.3152 + using google_breakpad::linked_ptr; 1.3153 + using google_breakpad::scoped_ptr; 1.3154 ++using google_breakpad::ustr__ZDcfa; 1.3155 ++using google_breakpad::ustr__ZDra; 1.3156 ++using google_breakpad::ustr__ZSebx; 1.3157 ++using google_breakpad::ustr__ZSebp; 1.3158 ++using google_breakpad::ustr__ZSedi; 1.3159 ++using google_breakpad::ustr__ZSesi; 1.3160 ++using google_breakpad::ustr__ZSesp; 1.3161 + 1.3162 + class TestCodeModule : public CodeModule { 1.3163 + public: 1.3164 + explicit TestCodeModule(string code_file) : code_file_(code_file) {} 1.3165 + virtual ~TestCodeModule() {} 1.3166 + 1.3167 + virtual uint64_t base_address() const { return 0; } 1.3168 + virtual uint64_t size() const { return 0xb000; } 1.3169 +@@ -119,34 +128,34 @@ 1.3170 + // association. (That is, ACTUAL's associations should be a subset of 1.3171 + // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and 1.3172 + // ".cfa". 1.3173 + static bool VerifyRegisters( 1.3174 + const char *file, int line, 1.3175 + const CFIFrameInfo::RegisterValueMap<uint32_t> &expected, 1.3176 + const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) { 1.3177 + CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; 1.3178 +- a = actual.find(".cfa"); 1.3179 ++ a = actual.find(ustr__ZDcfa()); 1.3180 + if (a == actual.end()) 1.3181 + return false; 1.3182 +- a = actual.find(".ra"); 1.3183 ++ a = actual.find(ustr__ZDra()); 1.3184 + if (a == actual.end()) 1.3185 + return false; 1.3186 + for (a = actual.begin(); a != actual.end(); a++) { 1.3187 + CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = 1.3188 + expected.find(a->first); 1.3189 + if (e == expected.end()) { 1.3190 + fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", 1.3191 +- file, line, a->first.c_str(), a->second); 1.3192 ++ file, line, FromUniqueString(a->first), a->second); 1.3193 + return false; 1.3194 + } 1.3195 + if (e->second != a->second) { 1.3196 + fprintf(stderr, 1.3197 + "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", 1.3198 +- file, line, a->first.c_str(), a->second, e->second); 1.3199 ++ file, line, FromUniqueString(a->first), a->second, e->second); 1.3200 + return false; 1.3201 + } 1.3202 + // Don't complain if this doesn't recover all registers. Although 1.3203 + // the DWARF spec says that unmentioned registers are undefined, 1.3204 + // GCC uses omission to mean that they are unchanged. 1.3205 + } 1.3206 + return true; 1.3207 + } 1.3208 +@@ -282,81 +291,81 @@ 1.3209 + 1.3210 + CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; 1.3211 + CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; 1.3212 + CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; 1.3213 + MockMemoryRegion memory; 1.3214 + 1.3215 + // Regardless of which instruction evaluation takes place at, it 1.3216 + // should produce the same values for the caller's registers. 1.3217 +- expected_caller_registers[".cfa"] = 0x1001c; 1.3218 +- expected_caller_registers[".ra"] = 0xf6438648; 1.3219 +- expected_caller_registers["$ebp"] = 0x10038; 1.3220 +- expected_caller_registers["$ebx"] = 0x98ecadc3; 1.3221 +- expected_caller_registers["$esi"] = 0x878f7524; 1.3222 +- expected_caller_registers["$edi"] = 0x6312f9a5; 1.3223 ++ expected_caller_registers[ustr__ZDcfa()] = 0x1001c; 1.3224 ++ expected_caller_registers[ustr__ZDra()] = 0xf6438648; 1.3225 ++ expected_caller_registers[ustr__ZSebp()] = 0x10038; 1.3226 ++ expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3; 1.3227 ++ expected_caller_registers[ustr__ZSesi()] = 0x878f7524; 1.3228 ++ expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5; 1.3229 + 1.3230 + frame.instruction = 0x3d40; 1.3231 + frame.module = &module1; 1.3232 + current_registers.clear(); 1.3233 +- current_registers["$esp"] = 0x10018; 1.3234 +- current_registers["$ebp"] = 0x10038; 1.3235 +- current_registers["$ebx"] = 0x98ecadc3; 1.3236 +- current_registers["$esi"] = 0x878f7524; 1.3237 +- current_registers["$edi"] = 0x6312f9a5; 1.3238 ++ current_registers[ustr__ZSesp()] = 0x10018; 1.3239 ++ current_registers[ustr__ZSebp()] = 0x10038; 1.3240 ++ current_registers[ustr__ZSebx()] = 0x98ecadc3; 1.3241 ++ current_registers[ustr__ZSesi()] = 0x878f7524; 1.3242 ++ current_registers[ustr__ZSedi()] = 0x6312f9a5; 1.3243 + cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 1.3244 + ASSERT_TRUE(cfi_frame_info.get()); 1.3245 + ASSERT_TRUE(cfi_frame_info.get() 1.3246 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.3247 + &caller_registers)); 1.3248 + ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 1.3249 + expected_caller_registers, caller_registers)); 1.3250 + 1.3251 + frame.instruction = 0x3d41; 1.3252 +- current_registers["$esp"] = 0x10014; 1.3253 ++ current_registers[ustr__ZSesp()] = 0x10014; 1.3254 + cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 1.3255 + ASSERT_TRUE(cfi_frame_info.get()); 1.3256 + ASSERT_TRUE(cfi_frame_info.get() 1.3257 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.3258 + &caller_registers)); 1.3259 + ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 1.3260 + expected_caller_registers, caller_registers)); 1.3261 + 1.3262 + frame.instruction = 0x3d43; 1.3263 +- current_registers["$ebp"] = 0x10014; 1.3264 ++ current_registers[ustr__ZSebp()] = 0x10014; 1.3265 + cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 1.3266 + ASSERT_TRUE(cfi_frame_info.get()); 1.3267 + ASSERT_TRUE(cfi_frame_info.get() 1.3268 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.3269 + &caller_registers)); 1.3270 + VerifyRegisters(__FILE__, __LINE__, 1.3271 + expected_caller_registers, caller_registers); 1.3272 + 1.3273 + frame.instruction = 0x3d54; 1.3274 +- current_registers["$ebx"] = 0x6864f054U; 1.3275 ++ current_registers[ustr__ZSebx()] = 0x6864f054U; 1.3276 + cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 1.3277 + ASSERT_TRUE(cfi_frame_info.get()); 1.3278 + ASSERT_TRUE(cfi_frame_info.get() 1.3279 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.3280 + &caller_registers)); 1.3281 + VerifyRegisters(__FILE__, __LINE__, 1.3282 + expected_caller_registers, caller_registers); 1.3283 + 1.3284 + frame.instruction = 0x3d5a; 1.3285 +- current_registers["$esi"] = 0x6285f79aU; 1.3286 ++ current_registers[ustr__ZSesi()] = 0x6285f79aU; 1.3287 + cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 1.3288 + ASSERT_TRUE(cfi_frame_info.get()); 1.3289 + ASSERT_TRUE(cfi_frame_info.get() 1.3290 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.3291 + &caller_registers)); 1.3292 + VerifyRegisters(__FILE__, __LINE__, 1.3293 + expected_caller_registers, caller_registers); 1.3294 + 1.3295 + frame.instruction = 0x3d84; 1.3296 +- current_registers["$edi"] = 0x64061449U; 1.3297 ++ current_registers[ustr__ZSedi()] = 0x64061449U; 1.3298 + cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 1.3299 + ASSERT_TRUE(cfi_frame_info.get()); 1.3300 + ASSERT_TRUE(cfi_frame_info.get() 1.3301 + ->FindCallerRegs<uint32_t>(current_registers, memory, 1.3302 + &caller_registers)); 1.3303 + VerifyRegisters(__FILE__, __LINE__, 1.3304 + expected_caller_registers, caller_registers); 1.3305 + 1.3306 +diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h 1.3307 +--- a/src/processor/postfix_evaluator-inl.h 1.3308 ++++ b/src/processor/postfix_evaluator-inl.h 1.3309 +@@ -51,23 +51,25 @@ 1.3310 + namespace google_breakpad { 1.3311 + 1.3312 + using std::istringstream; 1.3313 + using std::ostringstream; 1.3314 + 1.3315 + 1.3316 + // A small class used in Evaluate to make sure to clean up the stack 1.3317 + // before returning failure. 1.3318 ++template<typename ValueType> 1.3319 + class AutoStackClearer { 1.3320 + public: 1.3321 +- explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {} 1.3322 ++ explicit AutoStackClearer(vector<StackElem<ValueType> > *stack) 1.3323 ++ : stack_(stack) {} 1.3324 + ~AutoStackClearer() { stack_->clear(); } 1.3325 + 1.3326 + private: 1.3327 +- vector<string> *stack_; 1.3328 ++ vector<StackElem<ValueType> > *stack_; 1.3329 + }; 1.3330 + 1.3331 + 1.3332 + template<typename ValueType> 1.3333 + bool PostfixEvaluator<ValueType>::EvaluateToken( 1.3334 + const string &token, 1.3335 + const string &expression, 1.3336 + DictionaryValidityType *assigned) { 1.3337 +@@ -170,38 +172,57 @@ 1.3338 + BPLOG(INFO) << "Could not PopValue to get value to assign: " << 1.3339 + expression; 1.3340 + return false; 1.3341 + } 1.3342 + 1.3343 + // Assignment is only meaningful when assigning into an identifier. 1.3344 + // The identifier must name a variable, not a constant. Variables 1.3345 + // begin with '$'. 1.3346 +- string identifier; 1.3347 ++ const UniqueString* identifier; 1.3348 + if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { 1.3349 + BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " 1.3350 + "identifier is needed to assign " << 1.3351 + HexString(value) << ": " << expression; 1.3352 + return false; 1.3353 + } 1.3354 +- if (identifier.empty() || identifier[0] != '$') { 1.3355 ++ if (identifier == ustr__empty() || Index(identifier,0) != '$') { 1.3356 + BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " << 1.3357 + identifier << ": " << expression; 1.3358 + return false; 1.3359 + } 1.3360 + 1.3361 + (*dictionary_)[identifier] = value; 1.3362 + if (assigned) 1.3363 + (*assigned)[identifier] = true; 1.3364 + } else { 1.3365 +- // The token is not an operator, it's a literal value or an identifier. 1.3366 +- // Push it onto the stack as-is. Use push_back instead of PushValue 1.3367 +- // because PushValue pushes ValueType as a string, but token is already 1.3368 +- // a string. 1.3369 +- stack_.push_back(token); 1.3370 ++ // Push it onto the stack as-is, but first convert it either to a 1.3371 ++ // ValueType (if a literal) or to a UniqueString* (if an identifier). 1.3372 ++ // 1.3373 ++ // First, try to treat the value as a literal. Literals may have leading 1.3374 ++ // '-' sign, and the entire remaining string must be parseable as 1.3375 ++ // ValueType. If this isn't possible, it can't be a literal, so treat it 1.3376 ++ // as an identifier instead. 1.3377 ++ // 1.3378 ++ // Some versions of the libstdc++, the GNU standard C++ library, have 1.3379 ++ // stream extractors for unsigned integer values that permit a leading 1.3380 ++ // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we 1.3381 ++ // handle it explicitly here. 1.3382 ++ istringstream token_stream(token); 1.3383 ++ ValueType literal = ValueType(); 1.3384 ++ bool negative = false; 1.3385 ++ if (token_stream.peek() == '-') { 1.3386 ++ negative = true; 1.3387 ++ token_stream.get(); 1.3388 ++ } 1.3389 ++ if (token_stream >> literal && token_stream.peek() == EOF) { 1.3390 ++ PushValue(negative ? (-literal) : literal); 1.3391 ++ } else { 1.3392 ++ PushIdentifier(ToUniqueString(token)); 1.3393 ++ } 1.3394 + } 1.3395 + return true; 1.3396 + } 1.3397 + 1.3398 + template<typename ValueType> 1.3399 + bool PostfixEvaluator<ValueType>::EvaluateInternal( 1.3400 + const string &expression, 1.3401 + DictionaryValidityType *assigned) { 1.3402 +@@ -236,17 +257,17 @@ 1.3403 + // The expression is being exevaluated only for its side effects. Skip 1.3404 + // expressions that denote values only. 1.3405 + if (expr.how_ != Module::kExprPostfix) { 1.3406 + BPLOG(ERROR) << "Can't evaluate for side-effects: " << expr; 1.3407 + return false; 1.3408 + } 1.3409 + 1.3410 + // Ensure that the stack is cleared before returning. 1.3411 +- AutoStackClearer clearer(&stack_); 1.3412 ++ AutoStackClearer<ValueType> clearer(&stack_); 1.3413 + 1.3414 + if (!EvaluateInternal(expr.postfix_, assigned)) 1.3415 + return false; 1.3416 + 1.3417 + // If there's anything left on the stack, it indicates incomplete execution. 1.3418 + // This is a failure case. If the stack is empty, evalution was complete 1.3419 + // and successful. 1.3420 + if (stack_.empty()) 1.3421 +@@ -260,17 +281,17 @@ 1.3422 + bool PostfixEvaluator<ValueType>::EvaluateForValue(const Module::Expr& expr, 1.3423 + ValueType* result) { 1.3424 + switch (expr.how_) { 1.3425 + 1.3426 + // Postfix expression. Give to the evaluator and return the 1.3427 + // one-and-only stack element that should be left over. 1.3428 + case Module::kExprPostfix: { 1.3429 + // Ensure that the stack is cleared before returning. 1.3430 +- AutoStackClearer clearer(&stack_); 1.3431 ++ AutoStackClearer<ValueType> clearer(&stack_); 1.3432 + 1.3433 + if (!EvaluateInternal(expr.postfix_, NULL)) 1.3434 + return false; 1.3435 + 1.3436 + // A successful execution should leave exactly one value on the stack. 1.3437 + if (stack_.size() != 1) { 1.3438 + BPLOG(ERROR) << "Expression yielded bad number of results: " 1.3439 + << "'" << expr << "'"; 1.3440 +@@ -314,77 +335,56 @@ 1.3441 + return false; 1.3442 + } 1.3443 + } 1.3444 + 1.3445 + 1.3446 + template<typename ValueType> 1.3447 + typename PostfixEvaluator<ValueType>::PopResult 1.3448 + PostfixEvaluator<ValueType>::PopValueOrIdentifier( 1.3449 +- ValueType *value, string *identifier) { 1.3450 ++ ValueType *value, const UniqueString** identifier) { 1.3451 + // There needs to be at least one element on the stack to pop. 1.3452 + if (!stack_.size()) 1.3453 + return POP_RESULT_FAIL; 1.3454 + 1.3455 +- string token = stack_.back(); 1.3456 ++ StackElem<ValueType> el = stack_.back(); 1.3457 + stack_.pop_back(); 1.3458 + 1.3459 +- // First, try to treat the value as a literal. Literals may have leading 1.3460 +- // '-' sign, and the entire remaining string must be parseable as 1.3461 +- // ValueType. If this isn't possible, it can't be a literal, so treat it 1.3462 +- // as an identifier instead. 1.3463 +- // 1.3464 +- // Some versions of the libstdc++, the GNU standard C++ library, have 1.3465 +- // stream extractors for unsigned integer values that permit a leading 1.3466 +- // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we 1.3467 +- // handle it explicitly here. 1.3468 +- istringstream token_stream(token); 1.3469 +- ValueType literal = ValueType(); 1.3470 +- bool negative; 1.3471 +- if (token_stream.peek() == '-') { 1.3472 +- negative = true; 1.3473 +- token_stream.get(); 1.3474 +- } else { 1.3475 +- negative = false; 1.3476 +- } 1.3477 +- if (token_stream >> literal && token_stream.peek() == EOF) { 1.3478 +- if (value) { 1.3479 +- *value = literal; 1.3480 +- } 1.3481 +- if (negative) 1.3482 +- *value = -*value; 1.3483 ++ if (el.isValue) { 1.3484 ++ if (value) 1.3485 ++ *value = el.u.val; 1.3486 + return POP_RESULT_VALUE; 1.3487 + } else { 1.3488 +- if (identifier) { 1.3489 +- *identifier = token; 1.3490 +- } 1.3491 ++ if (identifier) 1.3492 ++ *identifier = el.u.ustr; 1.3493 + return POP_RESULT_IDENTIFIER; 1.3494 + } 1.3495 + } 1.3496 + 1.3497 + 1.3498 + template<typename ValueType> 1.3499 + bool PostfixEvaluator<ValueType>::PopValue(ValueType *value) { 1.3500 + ValueType literal = ValueType(); 1.3501 +- string token; 1.3502 ++ const UniqueString* token; 1.3503 + PopResult result; 1.3504 + if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) { 1.3505 + return false; 1.3506 + } else if (result == POP_RESULT_VALUE) { 1.3507 + // This is the easy case. 1.3508 + *value = literal; 1.3509 + } else { // result == POP_RESULT_IDENTIFIER 1.3510 + // There was an identifier at the top of the stack. Resolve it to a 1.3511 + // value by looking it up in the dictionary. 1.3512 + typename DictionaryType::const_iterator iterator = 1.3513 + dictionary_->find(token); 1.3514 + if (iterator == dictionary_->end()) { 1.3515 + // The identifier wasn't found in the dictionary. Don't imply any 1.3516 + // default value, just fail. 1.3517 +- BPLOG(INFO) << "Identifier " << token << " not in dictionary"; 1.3518 ++ BPLOG(INFO) << "Identifier " << FromUniqueString(token) 1.3519 ++ << " not in dictionary"; 1.3520 + return false; 1.3521 + } 1.3522 + 1.3523 + *value = iterator->second; 1.3524 + } 1.3525 + 1.3526 + return true; 1.3527 + } 1.3528 +@@ -394,18 +394,23 @@ 1.3529 + bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1, 1.3530 + ValueType *value2) { 1.3531 + return PopValue(value2) && PopValue(value1); 1.3532 + } 1.3533 + 1.3534 + 1.3535 + template<typename ValueType> 1.3536 + void PostfixEvaluator<ValueType>::PushValue(const ValueType &value) { 1.3537 +- ostringstream token_stream; 1.3538 +- token_stream << value; 1.3539 +- stack_.push_back(token_stream.str()); 1.3540 ++ StackElem<ValueType> el(value); 1.3541 ++ stack_.push_back(el); 1.3542 ++} 1.3543 ++ 1.3544 ++template<typename ValueType> 1.3545 ++void PostfixEvaluator<ValueType>::PushIdentifier(const UniqueString* str) { 1.3546 ++ StackElem<ValueType> el(str); 1.3547 ++ stack_.push_back(el); 1.3548 + } 1.3549 + 1.3550 + 1.3551 + } // namespace google_breakpad 1.3552 + 1.3553 + 1.3554 + #endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__ 1.3555 +diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h 1.3556 +--- a/src/processor/postfix_evaluator.h 1.3557 ++++ b/src/processor/postfix_evaluator.h 1.3558 +@@ -70,30 +70,41 @@ 1.3559 + #define PROCESSOR_POSTFIX_EVALUATOR_H__ 1.3560 + 1.3561 + 1.3562 + #include <map> 1.3563 + #include <string> 1.3564 + #include <vector> 1.3565 + 1.3566 + #include "common/using_std_string.h" 1.3567 ++#include "common/unique_string.h" 1.3568 + #include "common/module.h" 1.3569 + 1.3570 + namespace google_breakpad { 1.3571 + 1.3572 + using std::map; 1.3573 + using std::vector; 1.3574 + 1.3575 + class MemoryRegion; 1.3576 + 1.3577 ++// A union type for elements in the postfix evaluator's stack. 1.3578 ++template<typename ValueType> 1.3579 ++class StackElem { 1.3580 ++ public: 1.3581 ++ StackElem(ValueType val) { isValue = true; u.val = val; } 1.3582 ++ StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; } 1.3583 ++ bool isValue; 1.3584 ++ union { ValueType val; const UniqueString* ustr; } u; 1.3585 ++}; 1.3586 ++ 1.3587 + template<typename ValueType> 1.3588 + class PostfixEvaluator { 1.3589 + public: 1.3590 +- typedef map<string, ValueType> DictionaryType; 1.3591 +- typedef map<string, bool> DictionaryValidityType; 1.3592 ++ typedef map<const UniqueString*, ValueType> DictionaryType; 1.3593 ++ typedef map<const UniqueString*, bool> DictionaryValidityType; 1.3594 + 1.3595 + // Create a PostfixEvaluator object that may be used (with Evaluate) on 1.3596 + // one or more expressions. PostfixEvaluator does not take ownership of 1.3597 + // either argument. |memory| may be NULL, in which case dereferencing 1.3598 + // (^) will not be supported. |dictionary| may be NULL, but evaluation 1.3599 + // will fail in that case unless set_dictionary is used before calling 1.3600 + // Evaluate. 1.3601 + PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory) 1.3602 +@@ -128,24 +139,28 @@ 1.3603 + }; 1.3604 + 1.3605 + // Retrieves the topmost literal value, constant, or variable from the 1.3606 + // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal 1.3607 + // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER 1.3608 + // if the topmost entry is a constant or variable identifier, and sets 1.3609 + // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such 1.3610 + // as when the stack is empty. 1.3611 +- PopResult PopValueOrIdentifier(ValueType *value, string *identifier); 1.3612 ++ PopResult PopValueOrIdentifier(ValueType *value, 1.3613 ++ const UniqueString** identifier); 1.3614 + 1.3615 + // Retrieves the topmost value on the stack. If the topmost entry is 1.3616 + // an identifier, the dictionary is queried for the identifier's value. 1.3617 + // Returns false on failure, such as when the stack is empty or when 1.3618 + // a nonexistent identifier is named. 1.3619 + bool PopValue(ValueType *value); 1.3620 + 1.3621 ++ // Pushes a UniqueString* on the stack. 1.3622 ++ void PushIdentifier(const UniqueString* ustr); 1.3623 ++ 1.3624 + // Retrieves the top two values on the stack, in the style of PopValue. 1.3625 + // value2 is popped before value1, so that value1 corresponds to the 1.3626 + // entry that was pushed prior to value2. Returns false on failure. 1.3627 + bool PopValues(ValueType *value1, ValueType *value2); 1.3628 + 1.3629 + // Pushes a new value onto the stack. 1.3630 + void PushValue(const ValueType &value); 1.3631 + 1.3632 +@@ -166,15 +181,15 @@ 1.3633 + 1.3634 + // If non-NULL, the MemoryRegion used for dereference (^) operations. 1.3635 + // If NULL, dereferencing is unsupported and will fail. Weak pointer. 1.3636 + const MemoryRegion *memory_; 1.3637 + 1.3638 + // The stack contains state information as execution progresses. Values 1.3639 + // are pushed on to it as the expression string is read and as operations 1.3640 + // yield values; values are popped when used as operands to operators. 1.3641 +- vector<string> stack_; 1.3642 ++ vector<StackElem<ValueType> > stack_; 1.3643 + }; 1.3644 + 1.3645 + } // namespace google_breakpad 1.3646 + 1.3647 + 1.3648 + #endif // PROCESSOR_POSTFIX_EVALUATOR_H__ 1.3649 +diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc 1.3650 +--- a/src/processor/postfix_evaluator_unittest.cc 1.3651 ++++ b/src/processor/postfix_evaluator_unittest.cc 1.3652 +@@ -43,18 +43,32 @@ 1.3653 + #include "google_breakpad/processor/memory_region.h" 1.3654 + #include "processor/logging.h" 1.3655 + 1.3656 + 1.3657 + namespace { 1.3658 + 1.3659 + 1.3660 + using std::map; 1.3661 ++using google_breakpad::FromUniqueString; 1.3662 + using google_breakpad::MemoryRegion; 1.3663 + using google_breakpad::PostfixEvaluator; 1.3664 ++using google_breakpad::ToUniqueString; 1.3665 ++using google_breakpad::UniqueString; 1.3666 ++using google_breakpad::ustr__ZDcbParams; 1.3667 ++using google_breakpad::ustr__ZDcbSavedRegs; 1.3668 ++using google_breakpad::ustr__ZDcfa; 1.3669 ++using google_breakpad::ustr__ZDra; 1.3670 ++using google_breakpad::ustr__ZDraSearchStart; 1.3671 ++using google_breakpad::ustr__ZSebx; 1.3672 ++using google_breakpad::ustr__ZSebp; 1.3673 ++using google_breakpad::ustr__ZSedi; 1.3674 ++using google_breakpad::ustr__ZSeip; 1.3675 ++using google_breakpad::ustr__ZSesi; 1.3676 ++using google_breakpad::ustr__ZSesp; 1.3677 + 1.3678 + 1.3679 + // FakeMemoryRegion is used to test PostfixEvaluator's dereference (^) 1.3680 + // operator. The result of dereferencing a value is one greater than 1.3681 + // the value. 1.3682 + class FakeMemoryRegion : public MemoryRegion { 1.3683 + public: 1.3684 + virtual uint64_t GetBase() const { return 0; } 1.3685 +@@ -95,17 +109,17 @@ 1.3686 + // The list of tests. 1.3687 + const EvaluateTest *evaluate_tests; 1.3688 + 1.3689 + // The number of tests. 1.3690 + unsigned int evaluate_test_count; 1.3691 + 1.3692 + // Identifiers and their expected values upon completion of the Evaluate 1.3693 + // tests in the set. 1.3694 +- map<string, unsigned int> *validate_data; 1.3695 ++ map<const UniqueString*, unsigned int> *validate_data; 1.3696 + }; 1.3697 + 1.3698 + 1.3699 + struct EvaluateForValueTest { 1.3700 + // Expression passed to PostfixEvaluator::Evaluate. 1.3701 + const string expression; 1.3702 + 1.3703 + // True if the expression is expected to be evaluable, false if evaluation 1.3704 +@@ -147,39 +161,39 @@ 1.3705 + { "$rMul 9 6 * =", true }, // $rMul = 9 * 6 = 54 1.3706 + { "$rSub 9 6 - =", true }, // $rSub = 9 - 6 = 3 1.3707 + { "$rDivQ 9 6 / =", true }, // $rDivQ = 9 / 6 = 1 1.3708 + { "$rDivM 9 6 % =", true }, // $rDivM = 9 % 6 = 3 1.3709 + { "$rDeref 9 ^ =", true }, // $rDeref = ^9 = 10 (FakeMemoryRegion) 1.3710 + { "$rAlign 36 8 @ =", true }, // $rAlign = 36 @ 8 1.3711 + { "$rAdd3 2 2 + =$rMul2 9 6 * =", true } // smashed-equals tokenization 1.3712 + }; 1.3713 +- map<string, unsigned int> validate_data_0; 1.3714 +- validate_data_0["$rAdd"] = 8; 1.3715 +- validate_data_0["$rAdd2"] = 4; 1.3716 +- validate_data_0["$rSub"] = 3; 1.3717 +- validate_data_0["$rMul"] = 54; 1.3718 +- validate_data_0["$rDivQ"] = 1; 1.3719 +- validate_data_0["$rDivM"] = 3; 1.3720 +- validate_data_0["$rDeref"] = 10; 1.3721 +- validate_data_0["$rAlign"] = 32; 1.3722 +- validate_data_0["$rAdd3"] = 4; 1.3723 +- validate_data_0["$rMul2"] = 54; 1.3724 ++ map<const UniqueString*, unsigned int> validate_data_0; 1.3725 ++ validate_data_0[ToUniqueString("$rAdd")] = 8; 1.3726 ++ validate_data_0[ToUniqueString("$rAdd2")] = 4; 1.3727 ++ validate_data_0[ToUniqueString("$rSub")] = 3; 1.3728 ++ validate_data_0[ToUniqueString("$rMul")] = 54; 1.3729 ++ validate_data_0[ToUniqueString("$rDivQ")] = 1; 1.3730 ++ validate_data_0[ToUniqueString("$rDivM")] = 3; 1.3731 ++ validate_data_0[ToUniqueString("$rDeref")] = 10; 1.3732 ++ validate_data_0[ToUniqueString("$rAlign")] = 32; 1.3733 ++ validate_data_0[ToUniqueString("$rAdd3")] = 4; 1.3734 ++ validate_data_0[ToUniqueString("$rMul2")] = 54; 1.3735 + 1.3736 + // The second test set simulates a couple of MSVC program strings. 1.3737 + // The data is fudged a little bit because the tests use FakeMemoryRegion 1.3738 + // instead of a real stack snapshot, but the program strings are real and 1.3739 + // the implementation doesn't know or care that the data is not real. 1.3740 + PostfixEvaluator<unsigned int>::DictionaryType dictionary_1; 1.3741 +- dictionary_1["$ebp"] = 0xbfff0010; 1.3742 +- dictionary_1["$eip"] = 0x10000000; 1.3743 +- dictionary_1["$esp"] = 0xbfff0000; 1.3744 +- dictionary_1[".cbSavedRegs"] = 4; 1.3745 +- dictionary_1[".cbParams"] = 4; 1.3746 +- dictionary_1[".raSearchStart"] = 0xbfff0020; 1.3747 ++ dictionary_1[ustr__ZSebp()] = 0xbfff0010; 1.3748 ++ dictionary_1[ustr__ZSeip()] = 0x10000000; 1.3749 ++ dictionary_1[ustr__ZSesp()] = 0xbfff0000; 1.3750 ++ dictionary_1[ustr__ZDcbSavedRegs()] = 4; 1.3751 ++ dictionary_1[ustr__ZDcbParams()] = 4; 1.3752 ++ dictionary_1[ustr__ZDraSearchStart()] = 0xbfff0020; 1.3753 + const EvaluateTest evaluate_tests_1[] = { 1.3754 + { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = " 1.3755 + "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true }, 1.3756 + // Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015, 1.3757 + // $ebp = 0xbfff0011, $esp = 0xbfff0018, 1.3758 + // $L = 0xbfff000c, $P = 0xbfff001c 1.3759 + { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = " 1.3760 + "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =", 1.3761 +@@ -188,28 +202,28 @@ 1.3762 + // $ebp = 0xbfff0012, $esp = 0xbfff0019, 1.3763 + // $L = 0xbfff000d, $P = 0xbfff001d, 1.3764 + // $ebx = 0xbffefff6 1.3765 + { "$T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = " 1.3766 + "$esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = " 1.3767 + "$ebx $T0 28 - ^ =", 1.3768 + true } 1.3769 + }; 1.3770 +- map<string, unsigned int> validate_data_1; 1.3771 +- validate_data_1["$T0"] = 0xbfff0012; 1.3772 +- validate_data_1["$T1"] = 0xbfff0020; 1.3773 +- validate_data_1["$T2"] = 0xbfff0019; 1.3774 +- validate_data_1["$eip"] = 0xbfff0021; 1.3775 +- validate_data_1["$ebp"] = 0xbfff0012; 1.3776 +- validate_data_1["$esp"] = 0xbfff0024; 1.3777 +- validate_data_1["$L"] = 0xbfff000e; 1.3778 +- validate_data_1["$P"] = 0xbfff0028; 1.3779 +- validate_data_1["$ebx"] = 0xbffefff7; 1.3780 +- validate_data_1[".cbSavedRegs"] = 4; 1.3781 +- validate_data_1[".cbParams"] = 4; 1.3782 ++ map<const UniqueString*, unsigned int> validate_data_1; 1.3783 ++ validate_data_1[ToUniqueString("$T0")] = 0xbfff0012; 1.3784 ++ validate_data_1[ToUniqueString("$T1")] = 0xbfff0020; 1.3785 ++ validate_data_1[ToUniqueString("$T2")] = 0xbfff0019; 1.3786 ++ validate_data_1[ustr__ZSeip()] = 0xbfff0021; 1.3787 ++ validate_data_1[ustr__ZSebp()] = 0xbfff0012; 1.3788 ++ validate_data_1[ustr__ZSesp()] = 0xbfff0024; 1.3789 ++ validate_data_1[ToUniqueString("$L")] = 0xbfff000e; 1.3790 ++ validate_data_1[ToUniqueString("$P")] = 0xbfff0028; 1.3791 ++ validate_data_1[ustr__ZSebx()] = 0xbffefff7; 1.3792 ++ validate_data_1[ustr__ZDcbSavedRegs()] = 4; 1.3793 ++ validate_data_1[ustr__ZDcbParams()] = 4; 1.3794 + 1.3795 + EvaluateTestSet evaluate_test_sets[] = { 1.3796 + { &dictionary_0, evaluate_tests_0, 1.3797 + sizeof(evaluate_tests_0) / sizeof(EvaluateTest), &validate_data_0 }, 1.3798 + { &dictionary_1, evaluate_tests_1, 1.3799 + sizeof(evaluate_tests_1) / sizeof(EvaluateTest), &validate_data_1 }, 1.3800 + }; 1.3801 + 1.3802 +@@ -251,97 +265,100 @@ 1.3803 + evaluate_test->expression.c_str(), 1.3804 + evaluate_test->evaluable ? "evaluable" : "not evaluable", 1.3805 + result ? "evaluted" : "not evaluated"); 1.3806 + return false; 1.3807 + } 1.3808 + } 1.3809 + 1.3810 + // Validate the results. 1.3811 +- for (map<string, unsigned int>::const_iterator validate_iterator = 1.3812 ++ for (map<const UniqueString*, unsigned int>::const_iterator 1.3813 ++ validate_iterator = 1.3814 + evaluate_test_set->validate_data->begin(); 1.3815 + validate_iterator != evaluate_test_set->validate_data->end(); 1.3816 + ++validate_iterator) { 1.3817 +- const string identifier = validate_iterator->first; 1.3818 ++ const UniqueString* identifier = validate_iterator->first; 1.3819 + unsigned int expected_value = validate_iterator->second; 1.3820 + 1.3821 +- map<string, unsigned int>::const_iterator dictionary_iterator = 1.3822 ++ map<const UniqueString*, unsigned int>::const_iterator 1.3823 ++ dictionary_iterator = 1.3824 + evaluate_test_set->dictionary->find(identifier); 1.3825 + 1.3826 + // The identifier must exist in the dictionary. 1.3827 + if (dictionary_iterator == evaluate_test_set->dictionary->end()) { 1.3828 + fprintf(stderr, "FAIL: evaluate test set %d/%d, " 1.3829 + "validate identifier \"%s\", " 1.3830 + "expected %d, observed not found\n", 1.3831 + evaluate_test_set_index, evaluate_test_set_count, 1.3832 +- identifier.c_str(), expected_value); 1.3833 ++ FromUniqueString(identifier), expected_value); 1.3834 + return false; 1.3835 + } 1.3836 + 1.3837 + // The value in the dictionary must be the same as the expected value. 1.3838 + unsigned int observed_value = dictionary_iterator->second; 1.3839 + if (expected_value != observed_value) { 1.3840 + fprintf(stderr, "FAIL: evaluate test set %d/%d, " 1.3841 + "validate identifier \"%s\", " 1.3842 + "expected %d, observed %d\n", 1.3843 + evaluate_test_set_index, evaluate_test_set_count, 1.3844 +- identifier.c_str(), expected_value, observed_value); 1.3845 ++ FromUniqueString(identifier), expected_value, observed_value); 1.3846 + return false; 1.3847 + } 1.3848 + 1.3849 + // The value must be set in the "assigned" dictionary if it was a 1.3850 + // variable. It must not have been assigned if it was a constant. 1.3851 +- bool expected_assigned = identifier[0] == '$'; 1.3852 ++ bool expected_assigned = FromUniqueString(identifier)[0] == '$'; 1.3853 + bool observed_assigned = false; 1.3854 + PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator 1.3855 + iterator_assigned = assigned.find(identifier); 1.3856 + if (iterator_assigned != assigned.end()) { 1.3857 + observed_assigned = iterator_assigned->second; 1.3858 + } 1.3859 + if (expected_assigned != observed_assigned) { 1.3860 + fprintf(stderr, "FAIL: evaluate test set %d/%d, " 1.3861 + "validate assignment of \"%s\", " 1.3862 + "expected %d, observed %d\n", 1.3863 + evaluate_test_set_index, evaluate_test_set_count, 1.3864 +- identifier.c_str(), expected_assigned, observed_assigned); 1.3865 ++ FromUniqueString(identifier), expected_assigned, 1.3866 ++ observed_assigned); 1.3867 + return false; 1.3868 + } 1.3869 + } 1.3870 + } 1.3871 + 1.3872 + // EvaluateForValue tests. 1.3873 + PostfixEvaluator<unsigned int>::DictionaryType dictionary_2; 1.3874 +- dictionary_2["$ebp"] = 0xbfff0010; 1.3875 +- dictionary_2["$eip"] = 0x10000000; 1.3876 +- dictionary_2["$esp"] = 0xbfff0000; 1.3877 +- dictionary_2[".cbSavedRegs"] = 4; 1.3878 +- dictionary_2[".cbParams"] = 4; 1.3879 +- dictionary_2[".raSearchStart"] = 0xbfff0020; 1.3880 ++ dictionary_2[ustr__ZSebp()] = 0xbfff0010; 1.3881 ++ dictionary_2[ustr__ZSeip()] = 0x10000000; 1.3882 ++ dictionary_2[ustr__ZSesp()] = 0xbfff0000; 1.3883 ++ dictionary_2[ustr__ZDcbSavedRegs()] = 4; 1.3884 ++ dictionary_2[ustr__ZDcbParams()] = 4; 1.3885 ++ dictionary_2[ustr__ZDraSearchStart()] = 0xbfff0020; 1.3886 + const EvaluateForValueTest evaluate_for_value_tests_2[] = { 1.3887 + { "28907223", true, 28907223 }, // simple constant 1.3888 + { "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic 1.3889 + { "-870245 8769343 +", true, 7899098 }, // negative constants 1.3890 + { "$ebp $esp - $eip +", true, 0x10000010 }, // variable references 1.3891 + { "18929794 34015074", false, 0 }, // too many values 1.3892 + { "$ebp $ebp 4 - =", false, 0 }, // too few values 1.3893 + { "$new $eip = $new", true, 0x10000000 }, // make new variable 1.3894 + { "$new 4 +", true, 0x10000004 }, // see prior assignments 1.3895 + { ".cfa 42 = 10", false, 0 } // can't set constants 1.3896 + }; 1.3897 + const int evaluate_for_value_tests_2_size 1.3898 + = (sizeof (evaluate_for_value_tests_2) 1.3899 + / sizeof (evaluate_for_value_tests_2[0])); 1.3900 +- map<string, unsigned int> validate_data_2; 1.3901 +- validate_data_2["$eip"] = 0x10000000; 1.3902 +- validate_data_2["$ebp"] = 0xbfff000c; 1.3903 +- validate_data_2["$esp"] = 0xbfff0000; 1.3904 +- validate_data_2["$new"] = 0x10000000; 1.3905 +- validate_data_2[".cbSavedRegs"] = 4; 1.3906 +- validate_data_2[".cbParams"] = 4; 1.3907 +- validate_data_2[".raSearchStart"] = 0xbfff0020; 1.3908 ++ map<const UniqueString*, unsigned int> validate_data_2; 1.3909 ++ validate_data_2[ustr__ZSeip()] = 0x10000000; 1.3910 ++ validate_data_2[ustr__ZSebp()] = 0xbfff000c; 1.3911 ++ validate_data_2[ustr__ZSesp()] = 0xbfff0000; 1.3912 ++ validate_data_2[ToUniqueString("$new")] = 0x10000000; 1.3913 ++ validate_data_2[ustr__ZDcbSavedRegs()] = 4; 1.3914 ++ validate_data_2[ustr__ZDcbParams()] = 4; 1.3915 ++ validate_data_2[ustr__ZDraSearchStart()] = 0xbfff0020; 1.3916 + 1.3917 + postfix_evaluator.set_dictionary(&dictionary_2); 1.3918 + for (int i = 0; i < evaluate_for_value_tests_2_size; i++) { 1.3919 + const EvaluateForValueTest *test = &evaluate_for_value_tests_2[i]; 1.3920 + unsigned int result; 1.3921 + if (postfix_evaluator.EvaluateForValue(test->expression, &result) 1.3922 + != test->evaluable) { 1.3923 + fprintf(stderr, "FAIL: evaluate for value test %d, " 1.3924 +@@ -353,40 +370,43 @@ 1.3925 + if (test->evaluable && result != test->value) { 1.3926 + fprintf(stderr, "FAIL: evaluate for value test %d, " 1.3927 + "expected value to be 0x%x, but it was 0x%x\n", 1.3928 + i, test->value, result); 1.3929 + return false; 1.3930 + } 1.3931 + } 1.3932 + 1.3933 +- for (map<string, unsigned int>::iterator v = validate_data_2.begin(); 1.3934 ++ for (map<const UniqueString*, unsigned int>::iterator v = 1.3935 ++ validate_data_2.begin(); 1.3936 + v != validate_data_2.end(); v++) { 1.3937 +- map<string, unsigned int>::iterator a = dictionary_2.find(v->first); 1.3938 ++ map<const UniqueString*, unsigned int>::iterator a = 1.3939 ++ dictionary_2.find(v->first); 1.3940 + if (a == dictionary_2.end()) { 1.3941 + fprintf(stderr, "FAIL: evaluate for value dictionary check: " 1.3942 + "expected dict[\"%s\"] to be 0x%x, but it was unset\n", 1.3943 +- v->first.c_str(), v->second); 1.3944 ++ FromUniqueString(v->first), v->second); 1.3945 + return false; 1.3946 + } else if (a->second != v->second) { 1.3947 + fprintf(stderr, "FAIL: evaluate for value dictionary check: " 1.3948 + "expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n", 1.3949 +- v->first.c_str(), v->second, a->second); 1.3950 ++ FromUniqueString(v->first), v->second, a->second); 1.3951 + return false; 1.3952 + } 1.3953 + dictionary_2.erase(a); 1.3954 + } 1.3955 + 1.3956 +- map<string, unsigned int>::iterator remaining = dictionary_2.begin(); 1.3957 ++ map<const UniqueString*, unsigned int>::iterator remaining = 1.3958 ++ dictionary_2.begin(); 1.3959 + if (remaining != dictionary_2.end()) { 1.3960 + fprintf(stderr, "FAIL: evaluation of test expressions put unexpected " 1.3961 + "values in dictionary:\n"); 1.3962 + for (; remaining != dictionary_2.end(); remaining++) 1.3963 + fprintf(stderr, " dict[\"%s\"] == 0x%x\n", 1.3964 +- remaining->first.c_str(), remaining->second); 1.3965 ++ FromUniqueString(remaining->first), remaining->second); 1.3966 + return false; 1.3967 + } 1.3968 + 1.3969 + return true; 1.3970 + } 1.3971 + 1.3972 + 1.3973 + } // namespace 1.3974 +diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc 1.3975 +--- a/src/processor/stackwalker_amd64.cc 1.3976 ++++ b/src/processor/stackwalker_amd64.cc 1.3977 +@@ -50,49 +50,49 @@ 1.3978 + 1.3979 + const StackwalkerAMD64::CFIWalker::RegisterSet 1.3980 + StackwalkerAMD64::cfi_register_map_[] = { 1.3981 + // It may seem like $rip and $rsp are callee-saves, because the callee is 1.3982 + // responsible for having them restored upon return. But the callee_saves 1.3983 + // flags here really means that the walker should assume they're 1.3984 + // unchanged if the CFI doesn't mention them --- clearly wrong for $rip 1.3985 + // and $rsp. 1.3986 +- { "$rax", NULL, false, 1.3987 ++ { ToUniqueString("$rax"), NULL, false, 1.3988 + StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax }, 1.3989 +- { "$rdx", NULL, false, 1.3990 ++ { ToUniqueString("$rdx"), NULL, false, 1.3991 + StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx }, 1.3992 +- { "$rcx", NULL, false, 1.3993 ++ { ToUniqueString("$rcx"), NULL, false, 1.3994 + StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx }, 1.3995 +- { "$rbx", NULL, true, 1.3996 ++ { ToUniqueString("$rbx"), NULL, true, 1.3997 + StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx }, 1.3998 +- { "$rsi", NULL, false, 1.3999 ++ { ToUniqueString("$rsi"), NULL, false, 1.4000 + StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi }, 1.4001 +- { "$rdi", NULL, false, 1.4002 ++ { ToUniqueString("$rdi"), NULL, false, 1.4003 + StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi }, 1.4004 +- { "$rbp", NULL, true, 1.4005 ++ { ToUniqueString("$rbp"), NULL, true, 1.4006 + StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp }, 1.4007 +- { "$rsp", ".cfa", false, 1.4008 ++ { ToUniqueString("$rsp"), ToUniqueString(".cfa"), false, 1.4009 + StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp }, 1.4010 +- { "$r8", NULL, false, 1.4011 ++ { ToUniqueString("$r8"), NULL, false, 1.4012 + StackFrameAMD64::CONTEXT_VALID_R8, &MDRawContextAMD64::r8 }, 1.4013 +- { "$r9", NULL, false, 1.4014 ++ { ToUniqueString("$r9"), NULL, false, 1.4015 + StackFrameAMD64::CONTEXT_VALID_R9, &MDRawContextAMD64::r9 }, 1.4016 +- { "$r10", NULL, false, 1.4017 ++ { ToUniqueString("$r10"), NULL, false, 1.4018 + StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 }, 1.4019 +- { "$r11", NULL, false, 1.4020 ++ { ToUniqueString("$r11"), NULL, false, 1.4021 + StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 }, 1.4022 +- { "$r12", NULL, true, 1.4023 ++ { ToUniqueString("$r12"), NULL, true, 1.4024 + StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 }, 1.4025 +- { "$r13", NULL, true, 1.4026 ++ { ToUniqueString("$r13"), NULL, true, 1.4027 + StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 }, 1.4028 +- { "$r14", NULL, true, 1.4029 ++ { ToUniqueString("$r14"), NULL, true, 1.4030 + StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 }, 1.4031 +- { "$r15", NULL, true, 1.4032 ++ { ToUniqueString("$r15"), NULL, true, 1.4033 + StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 }, 1.4034 +- { "$rip", ".ra", false, 1.4035 ++ { ToUniqueString("$rip"), ToUniqueString(".ra"), false, 1.4036 + StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip }, 1.4037 + }; 1.4038 + 1.4039 + StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info, 1.4040 + const MDRawContextAMD64* context, 1.4041 + MemoryRegion* memory, 1.4042 + const CodeModules* modules, 1.4043 + StackFrameSymbolizer* resolver_helper) 1.4044 +diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc 1.4045 +--- a/src/processor/stackwalker_arm.cc 1.4046 ++++ b/src/processor/stackwalker_arm.cc 1.4047 +@@ -76,21 +76,30 @@ 1.4048 + return frame; 1.4049 + } 1.4050 + 1.4051 + StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo( 1.4052 + const vector<StackFrame*> &frames, 1.4053 + CFIFrameInfo* cfi_frame_info) { 1.4054 + StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); 1.4055 + 1.4056 +- static const char* register_names[] = { 1.4057 +- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1.4058 +- "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", 1.4059 +- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 1.4060 +- "fps", "cpsr", 1.4061 ++ static const UniqueString *register_names[] = { 1.4062 ++ ToUniqueString("r0"), ToUniqueString("r1"), 1.4063 ++ ToUniqueString("r2"), ToUniqueString("r3"), 1.4064 ++ ToUniqueString("r4"), ToUniqueString("r5"), 1.4065 ++ ToUniqueString("r6"), ToUniqueString("r7"), 1.4066 ++ ToUniqueString("r8"), ToUniqueString("r9"), 1.4067 ++ ToUniqueString("r10"), ToUniqueString("r11"), 1.4068 ++ ToUniqueString("r12"), ToUniqueString("sp"), 1.4069 ++ ToUniqueString("lr"), ToUniqueString("pc"), 1.4070 ++ ToUniqueString("f0"), ToUniqueString("f1"), 1.4071 ++ ToUniqueString("f2"), ToUniqueString("f3"), 1.4072 ++ ToUniqueString("f4"), ToUniqueString("f5"), 1.4073 ++ ToUniqueString("f6"), ToUniqueString("f7"), 1.4074 ++ ToUniqueString("fps"), ToUniqueString("cpsr"), 1.4075 + NULL 1.4076 + }; 1.4077 + 1.4078 + // Populate a dictionary with the valid register values in last_frame. 1.4079 + CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers; 1.4080 + for (int i = 0; register_names[i]; i++) 1.4081 + if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i)) 1.4082 + callee_registers[register_names[i]] = last_frame->context.iregs[i]; 1.4083 +@@ -119,17 +128,17 @@ 1.4084 + // Call Standard for the ARM Architecture, which the Linux ABI follows. 1.4085 + frame->context_validity |= StackFrameARM::RegisterValidFlag(i); 1.4086 + frame->context.iregs[i] = last_frame->context.iregs[i]; 1.4087 + } 1.4088 + } 1.4089 + // If the CFI doesn't recover the PC explicitly, then use .ra. 1.4090 + if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) { 1.4091 + CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry = 1.4092 +- caller_registers.find(".ra"); 1.4093 ++ caller_registers.find(ustr__ZDra()); 1.4094 + if (entry != caller_registers.end()) { 1.4095 + if (fp_register_ == -1) { 1.4096 + frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC; 1.4097 + frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second; 1.4098 + } else { 1.4099 + // The CFI updated the link register and not the program counter. 1.4100 + // Handle getting the program counter from the link register. 1.4101 + frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC; 1.4102 +@@ -138,17 +147,17 @@ 1.4103 + frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = 1.4104 + last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR]; 1.4105 + } 1.4106 + } 1.4107 + } 1.4108 + // If the CFI doesn't recover the SP explicitly, then use .cfa. 1.4109 + if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) { 1.4110 + CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry = 1.4111 +- caller_registers.find(".cfa"); 1.4112 ++ caller_registers.find(ustr__ZDcfa()); 1.4113 + if (entry != caller_registers.end()) { 1.4114 + frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP; 1.4115 + frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second; 1.4116 + } 1.4117 + } 1.4118 + 1.4119 + // If we didn't recover the PC and the SP, then the frame isn't very useful. 1.4120 + static const int essentials = (StackFrameARM::CONTEXT_VALID_SP 1.4121 +diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc 1.4122 +--- a/src/processor/stackwalker_x86.cc 1.4123 ++++ b/src/processor/stackwalker_x86.cc 1.4124 +@@ -53,33 +53,33 @@ 1.4125 + 1.4126 + const StackwalkerX86::CFIWalker::RegisterSet 1.4127 + StackwalkerX86::cfi_register_map_[] = { 1.4128 + // It may seem like $eip and $esp are callee-saves, because (with Unix or 1.4129 + // cdecl calling conventions) the callee is responsible for having them 1.4130 + // restored upon return. But the callee_saves flags here really means 1.4131 + // that the walker should assume they're unchanged if the CFI doesn't 1.4132 + // mention them, which is clearly wrong for $eip and $esp. 1.4133 +- { "$eip", ".ra", false, 1.4134 ++ { ToUniqueString("$eip"), ToUniqueString(".ra"), false, 1.4135 + StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip }, 1.4136 +- { "$esp", ".cfa", false, 1.4137 ++ { ToUniqueString("$esp"), ToUniqueString(".cfa"), false, 1.4138 + StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp }, 1.4139 +- { "$ebp", NULL, true, 1.4140 ++ { ToUniqueString("$ebp"), NULL, true, 1.4141 + StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp }, 1.4142 +- { "$eax", NULL, false, 1.4143 ++ { ToUniqueString("$eax"), NULL, false, 1.4144 + StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax }, 1.4145 +- { "$ebx", NULL, true, 1.4146 ++ { ToUniqueString("$ebx"), NULL, true, 1.4147 + StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx }, 1.4148 +- { "$ecx", NULL, false, 1.4149 ++ { ToUniqueString("$ecx"), NULL, false, 1.4150 + StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx }, 1.4151 +- { "$edx", NULL, false, 1.4152 ++ { ToUniqueString("$edx"), NULL, false, 1.4153 + StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx }, 1.4154 +- { "$esi", NULL, true, 1.4155 ++ { ToUniqueString("$esi"), NULL, true, 1.4156 + StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi }, 1.4157 +- { "$edi", NULL, true, 1.4158 ++ { ToUniqueString("$edi"), NULL, true, 1.4159 + StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi }, 1.4160 + }; 1.4161 + 1.4162 + StackwalkerX86::StackwalkerX86(const SystemInfo* system_info, 1.4163 + const MDRawContextX86* context, 1.4164 + MemoryRegion* memory, 1.4165 + const CodeModules* modules, 1.4166 + StackFrameSymbolizer* resolver_helper) 1.4167 +@@ -194,26 +194,26 @@ 1.4168 + } 1.4169 + } 1.4170 + 1.4171 + // Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used 1.4172 + // in each program string, and their previous values are known, so set them 1.4173 + // here. 1.4174 + PostfixEvaluator<uint32_t>::DictionaryType dictionary; 1.4175 + // Provide the current register values. 1.4176 +- dictionary["$ebp"] = last_frame->context.ebp; 1.4177 +- dictionary["$esp"] = last_frame->context.esp; 1.4178 ++ dictionary[ustr__ZSebp()] = last_frame->context.ebp; 1.4179 ++ dictionary[ustr__ZSesp()] = last_frame->context.esp; 1.4180 + // Provide constants from the debug info for last_frame and its callee. 1.4181 + // .cbCalleeParams is a Breakpad extension that allows us to use the 1.4182 + // PostfixEvaluator engine when certain types of debugging information 1.4183 + // are present without having to write the constants into the program 1.4184 + // string as literals. 1.4185 +- dictionary[".cbCalleeParams"] = last_frame_callee_parameter_size; 1.4186 +- dictionary[".cbSavedRegs"] = last_frame_info->saved_register_size; 1.4187 +- dictionary[".cbLocals"] = last_frame_info->local_size; 1.4188 ++ dictionary[ustr__ZDcbCalleeParams()] = last_frame_callee_parameter_size; 1.4189 ++ dictionary[ustr__ZDcbSavedRegs()] = last_frame_info->saved_register_size; 1.4190 ++ dictionary[ustr__ZDcbLocals()] = last_frame_info->local_size; 1.4191 + 1.4192 + uint32_t raSearchStart = last_frame->context.esp + 1.4193 + last_frame_callee_parameter_size + 1.4194 + last_frame_info->local_size + 1.4195 + last_frame_info->saved_register_size; 1.4196 + 1.4197 + uint32_t raSearchStartOld = raSearchStart; 1.4198 + uint32_t found = 0; // dummy value 1.4199 +@@ -232,20 +232,20 @@ 1.4200 + // Skip one slot from the stack and do another scan in order to get the 1.4201 + // actual return address. 1.4202 + raSearchStart += 4; 1.4203 + ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3); 1.4204 + } 1.4205 + 1.4206 + // The difference between raSearch and raSearchStart is unknown, 1.4207 + // but making them the same seems to work well in practice. 1.4208 +- dictionary[".raSearchStart"] = raSearchStart; 1.4209 +- dictionary[".raSearch"] = raSearchStart; 1.4210 ++ dictionary[ustr__ZDraSearchStart()] = raSearchStart; 1.4211 ++ dictionary[ustr__ZDraSearch()] = raSearchStart; 1.4212 + 1.4213 +- dictionary[".cbParams"] = last_frame_info->parameter_size; 1.4214 ++ dictionary[ustr__ZDcbParams()] = last_frame_info->parameter_size; 1.4215 + 1.4216 + // Decide what type of program string to use. The program string is in 1.4217 + // postfix notation and will be passed to PostfixEvaluator::Evaluate. 1.4218 + // Given the dictionary and the program string, it is possible to compute 1.4219 + // the return address and the values of other registers in the calling 1.4220 + // function. Because of bugs described below, the stack may need to be 1.4221 + // scanned for these values. The results of program string evaluation 1.4222 + // will be used to determine whether to scan for better values. 1.4223 +@@ -325,18 +325,18 @@ 1.4224 + } 1.4225 + 1.4226 + // Now crank it out, making sure that the program string set at least the 1.4227 + // two required variables. 1.4228 + PostfixEvaluator<uint32_t> evaluator = 1.4229 + PostfixEvaluator<uint32_t>(&dictionary, memory_); 1.4230 + PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity; 1.4231 + if (!evaluator.Evaluate(program_string, &dictionary_validity) || 1.4232 +- dictionary_validity.find("$eip") == dictionary_validity.end() || 1.4233 +- dictionary_validity.find("$esp") == dictionary_validity.end()) { 1.4234 ++ dictionary_validity.find(ustr__ZSeip()) == dictionary_validity.end() || 1.4235 ++ dictionary_validity.find(ustr__ZSesp()) == dictionary_validity.end()) { 1.4236 + // Program string evaluation failed. It may be that %eip is not somewhere 1.4237 + // with stack frame info, and %ebp is pointing to non-stack memory, so 1.4238 + // our evaluation couldn't succeed. We'll scan the stack for a return 1.4239 + // address. This can happen if the stack is in a module for which 1.4240 + // we don't have symbols, and that module is compiled without a 1.4241 + // frame pointer. 1.4242 + uint32_t location_start = last_frame->context.esp; 1.4243 + uint32_t location, eip; 1.4244 +@@ -344,69 +344,69 @@ 1.4245 + // if we can't find an instruction pointer even with stack scanning, 1.4246 + // give up. 1.4247 + return NULL; 1.4248 + } 1.4249 + 1.4250 + // This seems like a reasonable return address. Since program string 1.4251 + // evaluation failed, use it and set %esp to the location above the 1.4252 + // one where the return address was found. 1.4253 +- dictionary["$eip"] = eip; 1.4254 +- dictionary["$esp"] = location + 4; 1.4255 ++ dictionary[ustr__ZSeip()] = eip; 1.4256 ++ dictionary[ustr__ZSesp()] = location + 4; 1.4257 + trust = StackFrame::FRAME_TRUST_SCAN; 1.4258 + } 1.4259 + 1.4260 + // Since this stack frame did not use %ebp in a traditional way, 1.4261 + // locating the return address isn't entirely deterministic. In that 1.4262 + // case, the stack can be scanned to locate the return address. 1.4263 + // 1.4264 + // However, if program string evaluation resulted in both %eip and 1.4265 + // %ebp values of 0, trust that the end of the stack has been 1.4266 + // reached and don't scan for anything else. 1.4267 +- if (dictionary["$eip"] != 0 || dictionary["$ebp"] != 0) { 1.4268 ++ if (dictionary[ustr__ZSeip()] != 0 || dictionary[ustr__ZSebp()] != 0) { 1.4269 + int offset = 0; 1.4270 + 1.4271 + // This scan can only be done if a CodeModules object is available, to 1.4272 + // check that candidate return addresses are in fact inside a module. 1.4273 + // 1.4274 + // TODO(mmentovai): This ignores dynamically-generated code. One possible 1.4275 + // solution is to check the minidump's memory map to see if the candidate 1.4276 + // %eip value comes from a mapped executable page, although this would 1.4277 + // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad 1.4278 + // client doesn't currently write (it would need to call MiniDumpWriteDump 1.4279 + // with the MiniDumpWithFullMemoryInfo type bit set). Even given this 1.4280 + // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce 1.4281 + // an independent execute privilege on memory pages. 1.4282 + 1.4283 +- uint32_t eip = dictionary["$eip"]; 1.4284 ++ uint32_t eip = dictionary[ustr__ZSeip()]; 1.4285 + if (modules_ && !modules_->GetModuleForAddress(eip)) { 1.4286 + // The instruction pointer at .raSearchStart was invalid, so start 1.4287 + // looking one 32-bit word above that location. 1.4288 +- uint32_t location_start = dictionary[".raSearchStart"] + 4; 1.4289 ++ uint32_t location_start = dictionary[ustr__ZDraSearchStart()] + 4; 1.4290 + uint32_t location; 1.4291 + if (ScanForReturnAddress(location_start, &location, &eip)) { 1.4292 + // This is a better return address that what program string 1.4293 + // evaluation found. Use it, and set %esp to the location above the 1.4294 + // one where the return address was found. 1.4295 +- dictionary["$eip"] = eip; 1.4296 +- dictionary["$esp"] = location + 4; 1.4297 ++ dictionary[ustr__ZSeip()] = eip; 1.4298 ++ dictionary[ustr__ZSesp()] = location + 4; 1.4299 + offset = location - location_start; 1.4300 + trust = StackFrame::FRAME_TRUST_CFI_SCAN; 1.4301 + } 1.4302 + } 1.4303 + 1.4304 + if (recover_ebp) { 1.4305 + // When trying to recover the previous value of the frame pointer (%ebp), 1.4306 + // start looking at the lowest possible address in the saved-register 1.4307 + // area, and look at the entire saved register area, increased by the 1.4308 + // size of |offset| to account for additional data that may be on the 1.4309 + // stack. The scan is performed from the highest possible address to 1.4310 + // the lowest, because the expectation is that the function's prolog 1.4311 + // would have saved %ebp early. 1.4312 +- uint32_t ebp = dictionary["$ebp"]; 1.4313 ++ uint32_t ebp = dictionary[ustr__ZSebp()]; 1.4314 + 1.4315 + // When a scan for return address is used, it is possible to skip one or 1.4316 + // more frames (when return address is not in a known module). One 1.4317 + // indication for skipped frames is when the value of %ebp is lower than 1.4318 + // the location of the return address on the stack 1.4319 + bool has_skipped_frames = 1.4320 + (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset); 1.4321 + 1.4322 +@@ -420,49 +420,49 @@ 1.4323 + location >= location_end; 1.4324 + location -= 4) { 1.4325 + if (!memory_->GetMemoryAtAddress(location, &ebp)) 1.4326 + break; 1.4327 + 1.4328 + if (memory_->GetMemoryAtAddress(ebp, &value)) { 1.4329 + // The candidate value is a pointer to the same memory region 1.4330 + // (the stack). Prefer it as a recovered %ebp result. 1.4331 +- dictionary["$ebp"] = ebp; 1.4332 ++ dictionary[ustr__ZSebp()] = ebp; 1.4333 + break; 1.4334 + } 1.4335 + } 1.4336 + } 1.4337 + } 1.4338 + } 1.4339 + 1.4340 + // Create a new stack frame (ownership will be transferred to the caller) 1.4341 + // and fill it in. 1.4342 + StackFrameX86* frame = new StackFrameX86(); 1.4343 + 1.4344 + frame->trust = trust; 1.4345 + frame->context = last_frame->context; 1.4346 +- frame->context.eip = dictionary["$eip"]; 1.4347 +- frame->context.esp = dictionary["$esp"]; 1.4348 +- frame->context.ebp = dictionary["$ebp"]; 1.4349 ++ frame->context.eip = dictionary[ustr__ZSeip()]; 1.4350 ++ frame->context.esp = dictionary[ustr__ZSesp()]; 1.4351 ++ frame->context.ebp = dictionary[ustr__ZSebp()]; 1.4352 + frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | 1.4353 + StackFrameX86::CONTEXT_VALID_ESP | 1.4354 + StackFrameX86::CONTEXT_VALID_EBP; 1.4355 + 1.4356 + // These are nonvolatile (callee-save) registers, and the program string 1.4357 + // may have filled them in. 1.4358 +- if (dictionary_validity.find("$ebx") != dictionary_validity.end()) { 1.4359 +- frame->context.ebx = dictionary["$ebx"]; 1.4360 ++ if (dictionary_validity.find(ustr__ZSebx()) != dictionary_validity.end()) { 1.4361 ++ frame->context.ebx = dictionary[ustr__ZSebx()]; 1.4362 + frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX; 1.4363 + } 1.4364 +- if (dictionary_validity.find("$esi") != dictionary_validity.end()) { 1.4365 +- frame->context.esi = dictionary["$esi"]; 1.4366 ++ if (dictionary_validity.find(ustr__ZSesi()) != dictionary_validity.end()) { 1.4367 ++ frame->context.esi = dictionary[ustr__ZSesi()]; 1.4368 + frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI; 1.4369 + } 1.4370 +- if (dictionary_validity.find("$edi") != dictionary_validity.end()) { 1.4371 +- frame->context.edi = dictionary["$edi"]; 1.4372 ++ if (dictionary_validity.find(ustr__ZSedi()) != dictionary_validity.end()) { 1.4373 ++ frame->context.edi = dictionary[ustr__ZSedi()]; 1.4374 + frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI; 1.4375 + } 1.4376 + 1.4377 + return frame; 1.4378 + } 1.4379 + 1.4380 + StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( 1.4381 + const vector<StackFrame*> &frames, 1.4382 +diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj 1.4383 +--- a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj 1.4384 ++++ b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj 1.4385 +@@ -98,16 +98,22 @@ 1.4386 + B8C5B51B1166534700D34F4E /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650430B52F6D800611104 /* macho_id.cc */; }; 1.4387 + B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650450B52F6D800611104 /* macho_walker.cc */; }; 1.4388 + B8C5B51D1166534700D34F4E /* dump_syms.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* dump_syms.mm */; }; 1.4389 + B8C5B51E1166534700D34F4E /* dump_syms_tool.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */; }; 1.4390 + B8C5B523116653BA00D34F4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; }; 1.4391 + D21F97D711CBA12300239E38 /* test_assembler_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D9116CEC0600407530 /* test_assembler_unittest.cc */; }; 1.4392 + D21F97D811CBA13D00239E38 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; }; 1.4393 + D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; }; 1.4394 ++ D24997CC16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; }; 1.4395 ++ D24997CD16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; }; 1.4396 ++ D24997CE16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; }; 1.4397 ++ D2499A0016B9BA6A00E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; }; 1.4398 ++ D2499A0216B9BA9600E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; }; 1.4399 ++ D2499A0316B9BA9D00E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; }; 1.4400 + /* End PBXBuildFile section */ 1.4401 + 1.4402 + /* Begin PBXContainerItemProxy section */ 1.4403 + 8B31051411F100CF00FCF3E4 /* PBXContainerItemProxy */ = { 1.4404 + isa = PBXContainerItemProxy; 1.4405 + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; 1.4406 + proxyType = 1; 1.4407 + remoteGlobalIDString = D21F97D111CBA0F200239E38; 1.4408 +@@ -338,16 +344,18 @@ 1.4409 + B89E0E741166575200DD08C9 /* macho_dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_dump; sourceTree = BUILT_PRODUCTS_DIR; }; 1.4410 + B89E0E9511665A6400DD08C9 /* macho_reader_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_reader_unittest; sourceTree = BUILT_PRODUCTS_DIR; }; 1.4411 + 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; }; 1.4412 + 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; }; 1.4413 + 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; }; 1.4414 + B8C5B5111166531A00D34F4E /* dump_syms */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dump_syms; sourceTree = BUILT_PRODUCTS_DIR; }; 1.4415 + B8E8CA0C1156C854009E61B2 /* byteswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byteswap.h; path = ../../../common/mac/byteswap.h; sourceTree = SOURCE_ROOT; }; 1.4416 + D21F97D211CBA0F200239E38 /* test_assembler_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_assembler_unittest; sourceTree = BUILT_PRODUCTS_DIR; }; 1.4417 ++ D24997CA16B6C16800E588C5 /* unique_string.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = unique_string.cc; path = ../../../common/unique_string.cc; sourceTree = "<group>"; }; 1.4418 ++ D24997CB16B6C16800E588C5 /* unique_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unique_string.h; path = ../../../common/unique_string.h; sourceTree = "<group>"; }; 1.4419 + 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; }; 1.4420 + F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; }; 1.4421 + F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; }; 1.4422 + F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; }; 1.4423 + F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; }; 1.4424 + F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; }; 1.4425 + 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; }; 1.4426 + /* End PBXFileReference section */ 1.4427 +@@ -531,16 +539,18 @@ 1.4428 + D21F97D211CBA0F200239E38 /* test_assembler_unittest */, 1.4429 + ); 1.4430 + name = Products; 1.4431 + sourceTree = "<group>"; 1.4432 + }; 1.4433 + B88FAE1C11665FFD00407530 /* MODULE */ = { 1.4434 + isa = PBXGroup; 1.4435 + children = ( 1.4436 ++ D24997CA16B6C16800E588C5 /* unique_string.cc */, 1.4437 ++ D24997CB16B6C16800E588C5 /* unique_string.h */, 1.4438 + B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */, 1.4439 + B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */, 1.4440 + B88FB0D6116CEC0600407530 /* dwarf_cu_to_module_unittest.cc */, 1.4441 + B88FAE201166603300407530 /* dwarf_line_to_module.cc */, 1.4442 + B88FAE211166603300407530 /* dwarf_line_to_module.h */, 1.4443 + B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */, 1.4444 + B88FAE221166603300407530 /* language.cc */, 1.4445 + B88FAE231166603300407530 /* language.h */, 1.4446 +@@ -940,16 +950,17 @@ 1.4447 + }; 1.4448 + /* End PBXShellScriptBuildPhase section */ 1.4449 + 1.4450 + /* Begin PBXSourcesBuildPhase section */ 1.4451 + B84A91F1116CF784006C210E /* Sources */ = { 1.4452 + isa = PBXSourcesBuildPhase; 1.4453 + buildActionMask = 2147483647; 1.4454 + files = ( 1.4455 ++ D2499A0216B9BA9600E588C5 /* unique_string.cc in Sources */, 1.4456 + B84A91FB116CF7AF006C210E /* module.cc in Sources */, 1.4457 + B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */, 1.4458 + B84A91FD116CF7AF006C210E /* stabs_to_module_unittest.cc in Sources */, 1.4459 + ); 1.4460 + runOnlyForDeploymentPostprocessing = 0; 1.4461 + }; 1.4462 + B88FAF2C116A591D00407530 /* Sources */ = { 1.4463 + isa = PBXSourcesBuildPhase; 1.4464 +@@ -983,56 +994,60 @@ 1.4465 + runOnlyForDeploymentPostprocessing = 0; 1.4466 + }; 1.4467 + B88FB0B6116CEABF00407530 /* Sources */ = { 1.4468 + isa = PBXSourcesBuildPhase; 1.4469 + buildActionMask = 2147483647; 1.4470 + files = ( 1.4471 + B88FB0BD116CEAE000407530 /* module_unittest.cc in Sources */, 1.4472 + B88FB0C4116CEB4100407530 /* module.cc in Sources */, 1.4473 ++ D24997CE16B6C16800E588C5 /* unique_string.cc in Sources */, 1.4474 + ); 1.4475 + runOnlyForDeploymentPostprocessing = 0; 1.4476 + }; 1.4477 + B88FB0DC116CEEA800407530 /* Sources */ = { 1.4478 + isa = PBXSourcesBuildPhase; 1.4479 + buildActionMask = 2147483647; 1.4480 + files = ( 1.4481 + B88FB0E5116CEED300407530 /* dwarf2diehandler.cc in Sources */, 1.4482 + B88FB0E6116CEED300407530 /* dwarf2diehandler_unittest.cc in Sources */, 1.4483 + ); 1.4484 + runOnlyForDeploymentPostprocessing = 0; 1.4485 + }; 1.4486 + B88FB0EF116CEF1900407530 /* Sources */ = { 1.4487 + isa = PBXSourcesBuildPhase; 1.4488 + buildActionMask = 2147483647; 1.4489 + files = ( 1.4490 ++ D2499A0316B9BA9D00E588C5 /* unique_string.cc in Sources */, 1.4491 + B88FB0FA116CF00E00407530 /* dwarf_line_to_module.cc in Sources */, 1.4492 + B88FB0FE116CF02400407530 /* module.cc in Sources */, 1.4493 + B88FB0FB116CF00E00407530 /* dwarf_line_to_module_unittest.cc in Sources */, 1.4494 + ); 1.4495 + runOnlyForDeploymentPostprocessing = 0; 1.4496 + }; 1.4497 + B88FB107116CF07900407530 /* Sources */ = { 1.4498 + isa = PBXSourcesBuildPhase; 1.4499 + buildActionMask = 2147483647; 1.4500 + files = ( 1.4501 ++ D2499A0016B9BA6A00E588C5 /* unique_string.cc in Sources */, 1.4502 + B88FB112116CF1F000407530 /* dwarf_cu_to_module.cc in Sources */, 1.4503 + B88FB113116CF1F000407530 /* dwarf_cu_to_module_unittest.cc in Sources */, 1.4504 + B88FB114116CF1F000407530 /* language.cc in Sources */, 1.4505 + B88FB115116CF1F000407530 /* module.cc in Sources */, 1.4506 + ); 1.4507 + runOnlyForDeploymentPostprocessing = 0; 1.4508 + }; 1.4509 + B88FB11C116CF27F00407530 /* Sources */ = { 1.4510 + isa = PBXSourcesBuildPhase; 1.4511 + buildActionMask = 2147483647; 1.4512 + files = ( 1.4513 + B88FB129116CF2DD00407530 /* module.cc in Sources */, 1.4514 + B88FB12A116CF2DD00407530 /* dwarf_cfi_to_module.cc in Sources */, 1.4515 + B88FB12B116CF2DD00407530 /* dwarf_cfi_to_module_unittest.cc in Sources */, 1.4516 ++ D24997CD16B6C16800E588C5 /* unique_string.cc in Sources */, 1.4517 + ); 1.4518 + runOnlyForDeploymentPostprocessing = 0; 1.4519 + }; 1.4520 + B88FB132116CF30F00407530 /* Sources */ = { 1.4521 + isa = PBXSourcesBuildPhase; 1.4522 + buildActionMask = 2147483647; 1.4523 + files = ( 1.4524 + B88FB13D116CF38300407530 /* cfi_assembler.cc in Sources */, 1.4525 +@@ -1086,16 +1101,17 @@ 1.4526 + B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */, 1.4527 + B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */, 1.4528 + B88FAE281166603300407530 /* language.cc in Sources */, 1.4529 + B88FAE291166603300407530 /* module.cc in Sources */, 1.4530 + B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */, 1.4531 + B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */, 1.4532 + B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */, 1.4533 + 4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */, 1.4534 ++ D24997CC16B6C16800E588C5 /* unique_string.cc in Sources */, 1.4535 + ); 1.4536 + runOnlyForDeploymentPostprocessing = 0; 1.4537 + }; 1.4538 + D21F97CF11CBA0F200239E38 /* Sources */ = { 1.4539 + isa = PBXSourcesBuildPhase; 1.4540 + buildActionMask = 2147483647; 1.4541 + files = ( 1.4542 + D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */,