toolkit/crashreporter/breakpad-patches/03-unique-string.patch

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 # HG changeset patch
     2 # User Ted Mielczarek <ted.mielczarek@gmail.com>
     3 # Date 1360255134 18000
     4 #      Thu Feb 07 11:38:54 2013 -0500
     5 # Node ID 79cecfef3c2a10d719fe1af9fae2e5257109b028
     6 # Parent 08f184a7e6d6d15ecc20abd56bc4e36669c0c68a
     7 Rework PostfixEvaluator to use a UniqueString type
     8 Patch by Julian Seward <jseward@acm.org>, R=ted
    10 diff --git a/Makefile.am b/Makefile.am
    11 --- a/Makefile.am
    12 +++ b/Makefile.am
    13 @@ -134,16 +134,17 @@
    14  	src/google_breakpad/processor/source_line_resolver_interface.h \
    15  	src/google_breakpad/processor/stack_frame.h \
    16  	src/google_breakpad/processor/stack_frame_cpu.h \
    17  	src/google_breakpad/processor/stack_frame_symbolizer.h \
    18  	src/google_breakpad/processor/stackwalker.h \
    19  	src/google_breakpad/processor/symbol_supplier.h \
    20  	src/google_breakpad/processor/system_info.h \
    21  	src/common/module.cc \
    22 +	src/common/unique_string.cc \
    23  	src/processor/address_map-inl.h \
    24  	src/processor/address_map.h \
    25  	src/processor/basic_code_module.h \
    26  	src/processor/basic_code_modules.cc \
    27  	src/processor/basic_code_modules.h \
    28  	src/processor/basic_source_line_resolver_types.h \
    29  	src/processor/basic_source_line_resolver.cc \
    30  	src/processor/binarystream.h \
    31 @@ -430,16 +431,17 @@
    32  src_tools_linux_dump_syms_dump_syms_SOURCES = \
    33  	src/common/dwarf_cfi_to_module.cc \
    34  	src/common/dwarf_cu_to_module.cc \
    35  	src/common/dwarf_line_to_module.cc \
    36  	src/common/language.cc \
    37  	src/common/module.cc \
    38  	src/common/stabs_reader.cc \
    39  	src/common/stabs_to_module.cc \
    40 +	src/common/unique_string.cc \
    41  	src/common/dwarf/bytereader.cc \
    42  	src/common/dwarf/dwarf2diehandler.cc \
    43  	src/common/dwarf/dwarf2reader.cc \
    44  	src/common/linux/dump_symbols.cc \
    45  	src/common/linux/elf_symbols_to_module.cc \
    46  	src/common/linux/elfutils.cc \
    47  	src/common/linux/file_id.cc \
    48  	src/common/linux/linux_libc_support.cc \
    49 @@ -473,16 +475,17 @@
    50  	src/common/memory_range_unittest.cc \
    51  	src/common/module.cc \
    52  	src/common/module_unittest.cc \
    53  	src/common/stabs_reader.cc \
    54  	src/common/stabs_reader_unittest.cc \
    55  	src/common/stabs_to_module.cc \
    56  	src/common/stabs_to_module_unittest.cc \
    57  	src/common/test_assembler.cc \
    58 +	src/common/unique_string.cc \
    59  	src/common/dwarf/bytereader.cc \
    60  	src/common/dwarf/bytereader_unittest.cc \
    61  	src/common/dwarf/cfi_assembler.cc \
    62  	src/common/dwarf/dwarf2diehandler.cc \
    63  	src/common/dwarf/dwarf2diehandler_unittest.cc \
    64  	src/common/dwarf/dwarf2reader.cc \
    65  	src/common/dwarf/dwarf2reader_cfi_unittest.cc \
    66  	src/common/dwarf/dwarf2reader_die_unittest.cc \
    67 @@ -561,31 +564,33 @@
    68  src_processor_basic_source_line_resolver_unittest_CPPFLAGS = \
    69  	-I$(top_srcdir)/src \
    70  	-I$(top_srcdir)/src/testing/include \
    71  	-I$(top_srcdir)/src/testing/gtest/include \
    72  	-I$(top_srcdir)/src/testing/gtest \
    73  	-I$(top_srcdir)/src/testing
    74  src_processor_basic_source_line_resolver_unittest_LDADD = \
    75  	src/common/module.o \
    76 +	src/common/unique_string.o \
    77  	src/processor/basic_source_line_resolver.o \
    78  	src/processor/cfi_frame_info.o \
    79  	src/processor/pathname_stripper.o \
    80  	src/processor/logging.o \
    81  	src/processor/source_line_resolver_base.o \
    82  	src/processor/tokenize.o \
    83  	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
    85  src_processor_cfi_frame_info_unittest_SOURCES = \
    86  	src/processor/cfi_frame_info_unittest.cc \
    87  	src/testing/gtest/src/gtest-all.cc \
    88  	src/testing/gtest/src/gtest_main.cc \
    89  	src/testing/src/gmock-all.cc
    90  src_processor_cfi_frame_info_unittest_LDADD = \
    91  	src/common/module.o \
    92 +	src/common/unique_string.o \
    93  	src/processor/cfi_frame_info.o \
    94  	src/processor/logging.o \
    95  	src/processor/pathname_stripper.o \
    96  	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
    97  src_processor_cfi_frame_info_unittest_CPPFLAGS = \
    98  	-I$(top_srcdir)/src \
    99  	-I$(top_srcdir)/src/testing/include \
   100  	-I$(top_srcdir)/src/testing/gtest/include \
   101 @@ -606,16 +611,17 @@
   102  src_processor_exploitability_unittest_CPPFLAGS = \
   103  	-I$(top_srcdir)/src \
   104  	-I$(top_srcdir)/src/testing/include \
   105  	-I$(top_srcdir)/src/testing/gtest/include \
   106  	-I$(top_srcdir)/src/testing/gtest \
   107  	-I$(top_srcdir)/src/testing
   108  src_processor_exploitability_unittest_LDADD = \
   109  	src/common/module.o \
   110 +	src/common/unique_string.o \
   111  	src/processor/minidump_processor.o \
   112  	src/processor/process_state.o \
   113  	src/processor/disassembler_x86.o \
   114  	src/processor/exploitability.o \
   115  	src/processor/exploitability_win.o \
   116  	src/processor/basic_code_modules.o \
   117  	src/processor/basic_source_line_resolver.o \
   118  	src/processor/call_stack.o \
   119 @@ -659,16 +665,17 @@
   120  src_processor_fast_source_line_resolver_unittest_CPPFLAGS = \
   121  	-I$(top_srcdir)/src \
   122  	-I$(top_srcdir)/src/testing/include \
   123  	-I$(top_srcdir)/src/testing/gtest/include \
   124  	-I$(top_srcdir)/src/testing/gtest \
   125  	-I$(top_srcdir)/src/testing
   126  src_processor_fast_source_line_resolver_unittest_LDADD = \
   127  	src/common/module.o \
   128 +	src/common/unique_string.o \
   129  	src/processor/fast_source_line_resolver.o \
   130  	src/processor/basic_source_line_resolver.o \
   131  	src/processor/cfi_frame_info.o \
   132  	src/processor/module_comparer.o \
   133  	src/processor/module_serializer.o \
   134  	src/processor/pathname_stripper.o \
   135  	src/processor/logging.o \
   136  	src/processor/source_line_resolver_base.o \
   137 @@ -697,16 +704,17 @@
   138  src_processor_minidump_processor_unittest_CPPFLAGS = \
   139  	-I$(top_srcdir)/src \
   140  	-I$(top_srcdir)/src/testing/include \
   141  	-I$(top_srcdir)/src/testing/gtest/include \
   142  	-I$(top_srcdir)/src/testing/gtest \
   143  	-I$(top_srcdir)/src/testing
   144  src_processor_minidump_processor_unittest_LDADD = \
   145  	src/common/module.o \
   146 +	src/common/unique_string.o \
   147  	src/processor/basic_code_modules.o \
   148  	src/processor/basic_source_line_resolver.o \
   149  	src/processor/call_stack.o \
   150  	src/processor/cfi_frame_info.o \
   151  	src/processor/disassembler_x86.o \
   152  	src/processor/exploitability.o \
   153  	src/processor/exploitability_win.o \
   154  	src/processor/logging.o \
   155 @@ -812,16 +820,17 @@
   156  src_processor_pathname_stripper_unittest_LDADD = \
   157  	src/processor/pathname_stripper.o \
   158  	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
   160  src_processor_postfix_evaluator_unittest_SOURCES = \
   161  	src/processor/postfix_evaluator_unittest.cc
   162  src_processor_postfix_evaluator_unittest_LDADD = \
   163  	src/common/module.o \
   164 +	src/common/unique_string.o \
   165  	src/processor/logging.o \
   166  	src/processor/pathname_stripper.o \
   167  	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
   169  src_processor_range_map_unittest_SOURCES = \
   170  	src/processor/range_map_unittest.cc
   171  src_processor_range_map_unittest_LDADD = \
   172  	src/processor/logging.o \
   173 @@ -943,16 +952,17 @@
   174  	src/processor/logging.o \
   175  	src/processor/minidump.o \
   176  	src/processor/pathname_stripper.o
   178  src_processor_minidump_stackwalk_SOURCES = \
   179  	src/processor/minidump_stackwalk.cc
   180  src_processor_minidump_stackwalk_LDADD = \
   181  	src/common/module.o \
   182 +	src/common/unique_string.o \
   183  	src/processor/basic_code_modules.o \
   184  	src/processor/basic_source_line_resolver.o \
   185  	src/processor/binarystream.o \
   186  	src/processor/call_stack.o \
   187  	src/processor/cfi_frame_info.o \
   188  	src/processor/disassembler_x86.o \
   189  	src/processor/exploitability.o \
   190  	src/processor/exploitability_win.o \
   191 diff --git a/Makefile.in b/Makefile.in
   192 --- a/Makefile.in
   193 +++ b/Makefile.in
   194 @@ -267,18 +267,19 @@
   195  	src/google_breakpad/processor/source_line_resolver_base.h \
   196  	src/google_breakpad/processor/source_line_resolver_interface.h \
   197  	src/google_breakpad/processor/stack_frame.h \
   198  	src/google_breakpad/processor/stack_frame_cpu.h \
   199  	src/google_breakpad/processor/stack_frame_symbolizer.h \
   200  	src/google_breakpad/processor/stackwalker.h \
   201  	src/google_breakpad/processor/symbol_supplier.h \
   202  	src/google_breakpad/processor/system_info.h \
   203 -	src/common/module.cc src/processor/address_map-inl.h \
   204 -	src/processor/address_map.h src/processor/basic_code_module.h \
   205 +	src/common/module.cc src/common/unique_string.cc \
   206 +	src/processor/address_map-inl.h src/processor/address_map.h \
   207 +	src/processor/basic_code_module.h \
   208  	src/processor/basic_code_modules.cc \
   209  	src/processor/basic_code_modules.h \
   210  	src/processor/basic_source_line_resolver_types.h \
   211  	src/processor/basic_source_line_resolver.cc \
   212  	src/processor/binarystream.h src/processor/binarystream.cc \
   213  	src/processor/call_stack.cc src/processor/cfi_frame_info.cc \
   214  	src/processor/cfi_frame_info.h \
   215  	src/processor/contained_range_map-inl.h \
   216 @@ -332,16 +333,17 @@
   217  	src/processor/static_map_iterator-inl.h \
   218  	src/processor/static_map_iterator.h \
   219  	src/processor/static_map-inl.h src/processor/static_map.h \
   220  	src/processor/static_range_map-inl.h \
   221  	src/processor/static_range_map.h src/processor/tokenize.cc \
   222  	src/processor/tokenize.h
   223  @DISABLE_PROCESSOR_FALSE@am_src_libbreakpad_a_OBJECTS =  \
   224  @DISABLE_PROCESSOR_FALSE@	src/common/module.$(OBJEXT) \
   225 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.$(OBJEXT) \
   226  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.$(OBJEXT) \
   227  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.$(OBJEXT) \
   228  @DISABLE_PROCESSOR_FALSE@	src/processor/binarystream.$(OBJEXT) \
   229  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.$(OBJEXT) \
   230  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.$(OBJEXT) \
   231  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.$(OBJEXT) \
   232  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.$(OBJEXT) \
   233  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.$(OBJEXT) \
   234 @@ -525,17 +527,18 @@
   235  	src/common/dwarf_cu_to_module_unittest.cc \
   236  	src/common/dwarf_line_to_module.cc \
   237  	src/common/dwarf_line_to_module_unittest.cc \
   238  	src/common/language.cc src/common/memory_range_unittest.cc \
   239  	src/common/module.cc src/common/module_unittest.cc \
   240  	src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \
   241  	src/common/stabs_to_module.cc \
   242  	src/common/stabs_to_module_unittest.cc \
   243 -	src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
   244 +	src/common/test_assembler.cc src/common/unique_string.cc \
   245 +	src/common/dwarf/bytereader.cc \
   246  	src/common/dwarf/bytereader_unittest.cc \
   247  	src/common/dwarf/cfi_assembler.cc \
   248  	src/common/dwarf/dwarf2diehandler.cc \
   249  	src/common/dwarf/dwarf2diehandler_unittest.cc \
   250  	src/common/dwarf/dwarf2reader.cc \
   251  	src/common/dwarf/dwarf2reader_cfi_unittest.cc \
   252  	src/common/dwarf/dwarf2reader_die_unittest.cc \
   253  	src/common/linux/dump_symbols.cc \
   254 @@ -569,16 +572,17 @@
   255  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) \
   256  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-module.$(OBJEXT) \
   257  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT) \
   258  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT) \
   259  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT) \
   260  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT) \
   261  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT) \
   262  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT) \
   263 +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/src_common_dumper_unittest-unique_string.$(OBJEXT) \
   264  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT) \
   265  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.$(OBJEXT) \
   266  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-cfi_assembler.$(OBJEXT) \
   267  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.$(OBJEXT) \
   268  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT) \
   269  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \
   270  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \
   271  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \
   272 @@ -637,16 +641,17 @@
   273  	src/testing/gtest/src/gtest-all.cc \
   274  	src/testing/src/gmock-all.cc
   275  @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) \
   276  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_basic_source_line_resolver_unittest-gtest-all.$(OBJEXT) \
   277  @DISABLE_PROCESSOR_FALSE@	src/testing/src/src_processor_basic_source_line_resolver_unittest-gmock-all.$(OBJEXT)
   278  src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_basic_source_line_resolver_unittest_OBJECTS)
   279  @DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_DEPENDENCIES =  \
   280  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   281 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   282  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   283  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   284  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   285  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   286  @DISABLE_PROCESSOR_FALSE@	src/processor/source_line_resolver_base.o \
   287  @DISABLE_PROCESSOR_FALSE@	src/processor/tokenize.o \
   288  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1) \
   289  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1)
   290 @@ -671,16 +676,17 @@
   291  @DISABLE_PROCESSOR_FALSE@am_src_processor_cfi_frame_info_unittest_OBJECTS = src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.$(OBJEXT) \
   292  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_cfi_frame_info_unittest-gtest-all.$(OBJEXT) \
   293  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_cfi_frame_info_unittest-gtest_main.$(OBJEXT) \
   294  @DISABLE_PROCESSOR_FALSE@	src/testing/src/src_processor_cfi_frame_info_unittest-gmock-all.$(OBJEXT)
   295  src_processor_cfi_frame_info_unittest_OBJECTS =  \
   296  	$(am_src_processor_cfi_frame_info_unittest_OBJECTS)
   297  @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_DEPENDENCIES =  \
   298  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   299 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   300  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   301  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   302  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   303  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1) \
   304  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1)
   305  am__src_processor_contained_range_map_unittest_SOURCES_DIST =  \
   306  	src/processor/contained_range_map_unittest.cc
   307  @DISABLE_PROCESSOR_FALSE@am_src_processor_contained_range_map_unittest_OBJECTS = src/processor/contained_range_map_unittest.$(OBJEXT)
   308 @@ -713,16 +719,17 @@
   309  @DISABLE_PROCESSOR_FALSE@am_src_processor_exploitability_unittest_OBJECTS = src/processor/src_processor_exploitability_unittest-exploitability_unittest.$(OBJEXT) \
   310  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_exploitability_unittest-gtest-all.$(OBJEXT) \
   311  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_exploitability_unittest-gtest_main.$(OBJEXT) \
   312  @DISABLE_PROCESSOR_FALSE@	src/testing/src/src_processor_exploitability_unittest-gmock-all.$(OBJEXT)
   313  src_processor_exploitability_unittest_OBJECTS =  \
   314  	$(am_src_processor_exploitability_unittest_OBJECTS)
   315  @DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_DEPENDENCIES =  \
   316  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   317 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   318  @DISABLE_PROCESSOR_FALSE@	src/processor/minidump_processor.o \
   319  @DISABLE_PROCESSOR_FALSE@	src/processor/process_state.o \
   320  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.o \
   321  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.o \
   322  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.o \
   323  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.o \
   324  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   325  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.o \
   326 @@ -748,16 +755,17 @@
   327  	src/testing/gtest/src/gtest-all.cc \
   328  	src/testing/src/gmock-all.cc
   329  @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) \
   330  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_fast_source_line_resolver_unittest-gtest-all.$(OBJEXT) \
   331  @DISABLE_PROCESSOR_FALSE@	src/testing/src/src_processor_fast_source_line_resolver_unittest-gmock-all.$(OBJEXT)
   332  src_processor_fast_source_line_resolver_unittest_OBJECTS = $(am_src_processor_fast_source_line_resolver_unittest_OBJECTS)
   333  @DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_DEPENDENCIES =  \
   334  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   335 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   336  @DISABLE_PROCESSOR_FALSE@	src/processor/fast_source_line_resolver.o \
   337  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   338  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   339  @DISABLE_PROCESSOR_FALSE@	src/processor/module_comparer.o \
   340  @DISABLE_PROCESSOR_FALSE@	src/processor/module_serializer.o \
   341  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   342  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   343  @DISABLE_PROCESSOR_FALSE@	src/processor/source_line_resolver_base.o \
   344 @@ -794,16 +802,17 @@
   345  	src/testing/src/gmock-all.cc
   346  @DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_processor_unittest_OBJECTS = src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT) \
   347  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT) \
   348  @DISABLE_PROCESSOR_FALSE@	src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT)
   349  src_processor_minidump_processor_unittest_OBJECTS =  \
   350  	$(am_src_processor_minidump_processor_unittest_OBJECTS)
   351  @DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_DEPENDENCIES =  \
   352  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   353 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   354  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.o \
   355  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   356  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.o \
   357  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   358  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.o \
   359  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.o \
   360  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.o \
   361  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   362 @@ -826,16 +835,17 @@
   363  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1)
   364  am__src_processor_minidump_stackwalk_SOURCES_DIST =  \
   365  	src/processor/minidump_stackwalk.cc
   366  @DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_stackwalk_OBJECTS = src/processor/minidump_stackwalk.$(OBJEXT)
   367  src_processor_minidump_stackwalk_OBJECTS =  \
   368  	$(am_src_processor_minidump_stackwalk_OBJECTS)
   369  @DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_DEPENDENCIES =  \
   370  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   371 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   372  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.o \
   373  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   374  @DISABLE_PROCESSOR_FALSE@	src/processor/binarystream.o \
   375  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.o \
   376  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   377  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.o \
   378  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.o \
   379  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.o \
   380 @@ -889,16 +899,17 @@
   381  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1)
   382  am__src_processor_postfix_evaluator_unittest_SOURCES_DIST =  \
   383  	src/processor/postfix_evaluator_unittest.cc
   384  @DISABLE_PROCESSOR_FALSE@am_src_processor_postfix_evaluator_unittest_OBJECTS = src/processor/postfix_evaluator_unittest.$(OBJEXT)
   385  src_processor_postfix_evaluator_unittest_OBJECTS =  \
   386  	$(am_src_processor_postfix_evaluator_unittest_OBJECTS)
   387  @DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_DEPENDENCIES =  \
   388  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   389 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   390  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   391  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   392  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1) \
   393  @DISABLE_PROCESSOR_FALSE@	$(am__DEPENDENCIES_1)
   394  am__src_processor_range_map_unittest_SOURCES_DIST =  \
   395  	src/processor/range_map_unittest.cc
   396  @DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_unittest_OBJECTS = src/processor/range_map_unittest.$(OBJEXT)
   397  src_processor_range_map_unittest_OBJECTS =  \
   398 @@ -1069,33 +1080,35 @@
   399  src_tools_linux_core2md_core2md_OBJECTS =  \
   400  	$(am_src_tools_linux_core2md_core2md_OBJECTS)
   401  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_DEPENDENCIES = src/client/linux/libbreakpad_client.a
   402  am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST =  \
   403  	src/common/dwarf_cfi_to_module.cc \
   404  	src/common/dwarf_cu_to_module.cc \
   405  	src/common/dwarf_line_to_module.cc src/common/language.cc \
   406  	src/common/module.cc src/common/stabs_reader.cc \
   407 -	src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
   408 +	src/common/stabs_to_module.cc src/common/unique_string.cc \
   409 +	src/common/dwarf/bytereader.cc \
   410  	src/common/dwarf/dwarf2diehandler.cc \
   411  	src/common/dwarf/dwarf2reader.cc \
   412  	src/common/linux/dump_symbols.cc \
   413  	src/common/linux/elf_symbols_to_module.cc \
   414  	src/common/linux/elfutils.cc src/common/linux/file_id.cc \
   415  	src/common/linux/linux_libc_support.cc \
   416  	src/common/linux/memory_mapped_file.cc \
   417  	src/common/linux/safe_readlink.cc \
   418  	src/tools/linux/dump_syms/dump_syms.cc
   419  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_dump_syms_dump_syms_OBJECTS = src/common/dwarf_cfi_to_module.$(OBJEXT) \
   420  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf_cu_to_module.$(OBJEXT) \
   421  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf_line_to_module.$(OBJEXT) \
   422  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/language.$(OBJEXT) \
   423  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/module.$(OBJEXT) \
   424  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_reader.$(OBJEXT) \
   425  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_to_module.$(OBJEXT) \
   426 +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/unique_string.$(OBJEXT) \
   427  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/bytereader.$(OBJEXT) \
   428  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2diehandler.$(OBJEXT) \
   429  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2reader.$(OBJEXT) \
   430  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/dump_symbols.$(OBJEXT) \
   431  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/elf_symbols_to_module.$(OBJEXT) \
   432  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/elfutils.$(OBJEXT) \
   433  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/file_id.$(OBJEXT) \
   434  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/linux_libc_support.$(OBJEXT) \
   435 @@ -1416,16 +1429,17 @@
   436  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/source_line_resolver_interface.h \
   437  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/stack_frame.h \
   438  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/stack_frame_cpu.h \
   439  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/stack_frame_symbolizer.h \
   440  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/stackwalker.h \
   441  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/symbol_supplier.h \
   442  @DISABLE_PROCESSOR_FALSE@	src/google_breakpad/processor/system_info.h \
   443  @DISABLE_PROCESSOR_FALSE@	src/common/module.cc \
   444 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.cc \
   445  @DISABLE_PROCESSOR_FALSE@	src/processor/address_map-inl.h \
   446  @DISABLE_PROCESSOR_FALSE@	src/processor/address_map.h \
   447  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_module.h \
   448  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.cc \
   449  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.h \
   450  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver_types.h \
   451  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.cc \
   452  @DISABLE_PROCESSOR_FALSE@	src/processor/binarystream.h \
   453 @@ -1618,16 +1632,17 @@
   454  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_dump_syms_dump_syms_SOURCES = \
   455  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf_cfi_to_module.cc \
   456  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf_cu_to_module.cc \
   457  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf_line_to_module.cc \
   458  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/language.cc \
   459  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/module.cc \
   460  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_reader.cc \
   461  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_to_module.cc \
   462 +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/unique_string.cc \
   463  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/bytereader.cc \
   464  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2diehandler.cc \
   465  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2reader.cc \
   466  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/dump_symbols.cc \
   467  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/elf_symbols_to_module.cc \
   468  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/elfutils.cc \
   469  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/file_id.cc \
   470  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/linux/linux_libc_support.cc \
   471 @@ -1661,16 +1676,17 @@
   472  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/memory_range_unittest.cc \
   473  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/module.cc \
   474  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/module_unittest.cc \
   475  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_reader.cc \
   476  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_reader_unittest.cc \
   477  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_to_module.cc \
   478  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/stabs_to_module_unittest.cc \
   479  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/test_assembler.cc \
   480 +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/unique_string.cc \
   481  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/bytereader.cc \
   482  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/bytereader_unittest.cc \
   483  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/cfi_assembler.cc \
   484  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2diehandler.cc \
   485  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2diehandler_unittest.cc \
   486  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2reader.cc \
   487  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2reader_cfi_unittest.cc \
   488  @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dwarf/dwarf2reader_die_unittest.cc \
   489 @@ -1753,32 +1769,34 @@
   490  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src \
   491  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/include \
   492  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest/include \
   493  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest \
   494  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing
   496  @DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_LDADD = \
   497  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   498 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   499  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   500  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   501  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   502  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   503  @DISABLE_PROCESSOR_FALSE@	src/processor/source_line_resolver_base.o \
   504  @DISABLE_PROCESSOR_FALSE@	src/processor/tokenize.o \
   505  @DISABLE_PROCESSOR_FALSE@	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
   507  @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \
   508  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info_unittest.cc \
   509  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/gtest-all.cc \
   510  @DISABLE_PROCESSOR_FALSE@	src/testing/gtest/src/gtest_main.cc \
   511  @DISABLE_PROCESSOR_FALSE@	src/testing/src/gmock-all.cc
   513  @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_LDADD = \
   514  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   515 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   516  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   517  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   518  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   519  @DISABLE_PROCESSOR_FALSE@	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
   521  @DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_CPPFLAGS = \
   522  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src \
   523  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/include \
   524 @@ -1803,16 +1821,17 @@
   525  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src \
   526  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/include \
   527  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest/include \
   528  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest \
   529  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing
   531  @DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_LDADD = \
   532  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   533 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   534  @DISABLE_PROCESSOR_FALSE@	src/processor/minidump_processor.o \
   535  @DISABLE_PROCESSOR_FALSE@	src/processor/process_state.o \
   536  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.o \
   537  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.o \
   538  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.o \
   539  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.o \
   540  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   541  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.o \
   542 @@ -1860,16 +1879,17 @@
   543  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src \
   544  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/include \
   545  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest/include \
   546  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest \
   547  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing
   549  @DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_LDADD = \
   550  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   551 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   552  @DISABLE_PROCESSOR_FALSE@	src/processor/fast_source_line_resolver.o \
   553  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   554  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   555  @DISABLE_PROCESSOR_FALSE@	src/processor/module_comparer.o \
   556  @DISABLE_PROCESSOR_FALSE@	src/processor/module_serializer.o \
   557  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   558  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   559  @DISABLE_PROCESSOR_FALSE@	src/processor/source_line_resolver_base.o \
   560 @@ -1902,16 +1922,17 @@
   561  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src \
   562  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/include \
   563  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest/include \
   564  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing/gtest \
   565  @DISABLE_PROCESSOR_FALSE@	-I$(top_srcdir)/src/testing
   567  @DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_LDADD = \
   568  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   569 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   570  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.o \
   571  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   572  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.o \
   573  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   574  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.o \
   575  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.o \
   576  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.o \
   577  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   578 @@ -2029,16 +2050,17 @@
   579  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   580  @DISABLE_PROCESSOR_FALSE@	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
   582  @DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_SOURCES = \
   583  @DISABLE_PROCESSOR_FALSE@	src/processor/postfix_evaluator_unittest.cc
   585  @DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_LDADD = \
   586  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   587 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   588  @DISABLE_PROCESSOR_FALSE@	src/processor/logging.o \
   589  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o \
   590  @DISABLE_PROCESSOR_FALSE@	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
   592  @DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_SOURCES = \
   593  @DISABLE_PROCESSOR_FALSE@	src/processor/range_map_unittest.cc
   595  @DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_LDADD = \
   596 @@ -2169,16 +2191,17 @@
   597  @DISABLE_PROCESSOR_FALSE@	src/processor/minidump.o \
   598  @DISABLE_PROCESSOR_FALSE@	src/processor/pathname_stripper.o
   600  @DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_SOURCES = \
   601  @DISABLE_PROCESSOR_FALSE@	src/processor/minidump_stackwalk.cc
   603  @DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_LDADD = \
   604  @DISABLE_PROCESSOR_FALSE@	src/common/module.o \
   605 +@DISABLE_PROCESSOR_FALSE@	src/common/unique_string.o \
   606  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_code_modules.o \
   607  @DISABLE_PROCESSOR_FALSE@	src/processor/basic_source_line_resolver.o \
   608  @DISABLE_PROCESSOR_FALSE@	src/processor/binarystream.o \
   609  @DISABLE_PROCESSOR_FALSE@	src/processor/call_stack.o \
   610  @DISABLE_PROCESSOR_FALSE@	src/processor/cfi_frame_info.o \
   611  @DISABLE_PROCESSOR_FALSE@	src/processor/disassembler_x86.o \
   612  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability.o \
   613  @DISABLE_PROCESSOR_FALSE@	src/processor/exploitability_win.o \
   614 @@ -2527,16 +2550,18 @@
   615  	@$(MKDIR_P) src/client/linux
   616  	@: > src/client/linux/$(am__dirstamp)
   617  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)
   618  	-rm -f src/client/linux/libbreakpad_client.a
   619  	$(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)
   620  	$(RANLIB) src/client/linux/libbreakpad_client.a
   621  src/common/module.$(OBJEXT): src/common/$(am__dirstamp) \
   622  	src/common/$(DEPDIR)/$(am__dirstamp)
   623 +src/common/unique_string.$(OBJEXT): src/common/$(am__dirstamp) \
   624 +	src/common/$(DEPDIR)/$(am__dirstamp)
   625  src/processor/$(am__dirstamp):
   626  	@$(MKDIR_P) src/processor
   627  	@: > src/processor/$(am__dirstamp)
   628  src/processor/$(DEPDIR)/$(am__dirstamp):
   629  	@$(MKDIR_P) src/processor/$(DEPDIR)
   630  	@: > src/processor/$(DEPDIR)/$(am__dirstamp)
   631  src/processor/basic_code_modules.$(OBJEXT):  \
   632  	src/processor/$(am__dirstamp) \
   633 @@ -2863,16 +2888,19 @@
   634  	src/common/$(am__dirstamp) \
   635  	src/common/$(DEPDIR)/$(am__dirstamp)
   636  src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT):  \
   637  	src/common/$(am__dirstamp) \
   638  	src/common/$(DEPDIR)/$(am__dirstamp)
   639  src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT):  \
   640  	src/common/$(am__dirstamp) \
   641  	src/common/$(DEPDIR)/$(am__dirstamp)
   642 +src/common/src_common_dumper_unittest-unique_string.$(OBJEXT):  \
   643 +	src/common/$(am__dirstamp) \
   644 +	src/common/$(DEPDIR)/$(am__dirstamp)
   645  src/common/dwarf/$(am__dirstamp):
   646  	@$(MKDIR_P) src/common/dwarf
   647  	@: > src/common/dwarf/$(am__dirstamp)
   648  src/common/dwarf/$(DEPDIR)/$(am__dirstamp):
   649  	@$(MKDIR_P) src/common/dwarf/$(DEPDIR)
   650  	@: > src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
   651  src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT):  \
   652  	src/common/dwarf/$(am__dirstamp) \
   653 @@ -3470,28 +3498,30 @@
   654  	-rm -f src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT)
   655  	-rm -f src/common/src_common_dumper_unittest-module.$(OBJEXT)
   656  	-rm -f src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT)
   657  	-rm -f src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT)
   658  	-rm -f src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT)
   659  	-rm -f src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT)
   660  	-rm -f src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT)
   661  	-rm -f src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT)
   662 +	-rm -f src/common/src_common_dumper_unittest-unique_string.$(OBJEXT)
   663  	-rm -f src/common/src_common_test_assembler_unittest-test_assembler.$(OBJEXT)
   664  	-rm -f src/common/src_common_test_assembler_unittest-test_assembler_unittest.$(OBJEXT)
   665  	-rm -f src/common/src_processor_minidump_unittest-test_assembler.$(OBJEXT)
   666  	-rm -f src/common/src_processor_stackwalker_amd64_unittest-test_assembler.$(OBJEXT)
   667  	-rm -f src/common/src_processor_stackwalker_arm_unittest-test_assembler.$(OBJEXT)
   668  	-rm -f src/common/src_processor_stackwalker_x86_unittest-test_assembler.$(OBJEXT)
   669  	-rm -f src/common/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT)
   670  	-rm -f src/common/stabs_reader.$(OBJEXT)
   671  	-rm -f src/common/stabs_to_module.$(OBJEXT)
   672  	-rm -f src/common/string_conversion.$(OBJEXT)
   673  	-rm -f src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.$(OBJEXT)
   674  	-rm -f src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT)
   675 +	-rm -f src/common/unique_string.$(OBJEXT)
   676  	-rm -f src/processor/address_map_unittest.$(OBJEXT)
   677  	-rm -f src/processor/basic_code_modules.$(OBJEXT)
   678  	-rm -f src/processor/basic_source_line_resolver.$(OBJEXT)
   679  	-rm -f src/processor/binarystream.$(OBJEXT)
   680  	-rm -f src/processor/call_stack.$(OBJEXT)
   681  	-rm -f src/processor/cfi_frame_info.$(OBJEXT)
   682  	-rm -f src/processor/contained_range_map_unittest.$(OBJEXT)
   683  	-rm -f src/processor/disassembler_x86.$(OBJEXT)
   684 @@ -3663,26 +3693,28 @@
   685  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po@am__quote@
   686  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po@am__quote@
   687  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po@am__quote@
   688  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po@am__quote@
   689  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Po@am__quote@
   690  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Po@am__quote@
   691  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Po@am__quote@
   692  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po@am__quote@
   693 +@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-unique_string.Po@am__quote@
   694  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Po@am__quote@
   695  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Po@am__quote@
   696  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po@am__quote@
   697  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Po@am__quote@
   698  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Po@am__quote@
   699  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Po@am__quote@
   700  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po@am__quote@
   701  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_reader.Po@am__quote@
   702  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_to_module.Po@am__quote@
   703  @AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/string_conversion.Po@am__quote@
   704 +@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/unique_string.Po@am__quote@
   705  @AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/breakpad_getcontext.Po@am__quote@
   706  @AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Po@am__quote@
   707  @AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po@am__quote@
   708  @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/bytereader.Po@am__quote@
   709  @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2diehandler.Po@am__quote@
   710  @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2reader.Po@am__quote@
   711  @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po@am__quote@
   712  @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po@am__quote@
   713 @@ -4474,16 +4506,30 @@
   715  src/common/src_common_dumper_unittest-test_assembler.obj: src/common/test_assembler.cc
   716  @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`
   717  @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
   718  @AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/common/test_assembler.cc' object='src/common/src_common_dumper_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
   719  @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
   720  @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`
   722 +src/common/src_common_dumper_unittest-unique_string.o: src/common/unique_string.cc
   723 +@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
   724 +@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
   725 +@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/common/unique_string.cc' object='src/common/src_common_dumper_unittest-unique_string.o' libtool=no @AMDEPBACKSLASH@
   726 +@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
   727 +@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
   728 +
   729 +src/common/src_common_dumper_unittest-unique_string.obj: src/common/unique_string.cc
   730 +@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`
   731 +@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
   732 +@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/common/unique_string.cc' object='src/common/src_common_dumper_unittest-unique_string.obj' libtool=no @AMDEPBACKSLASH@
   733 +@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
   734 +@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`
   735 +
   736  src/common/dwarf/src_common_dumper_unittest-bytereader.o: src/common/dwarf/bytereader.cc
   737  @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
   738  @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
   739  @AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader.o' libtool=no @AMDEPBACKSLASH@
   740  @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
   741  @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
   743  src/common/dwarf/src_common_dumper_unittest-bytereader.obj: src/common/dwarf/bytereader.cc
   744 diff --git a/src/common/dwarf_cfi_to_module.cc b/src/common/dwarf_cfi_to_module.cc
   745 --- a/src/common/dwarf_cfi_to_module.cc
   746 +++ b/src/common/dwarf_cfi_to_module.cc
   747 @@ -37,40 +37,44 @@
   748  #include <sstream>
   750  #include "common/dwarf_cfi_to_module.h"
   752  namespace google_breakpad {
   754  using std::ostringstream;
   756 -vector<string> DwarfCFIToModule::RegisterNames::MakeVector(
   757 -    const char * const *strings,
   758 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::MakeVector(
   759 +    const char* const* strings,
   760      size_t size) {
   761 -  vector<string> names(strings, strings + size);
   762 +  vector<const UniqueString*> names(size, NULL);
   763 +  for (size_t i = 0; i < size; ++i) {
   764 +    names[i] = ToUniqueString(strings[i]);
   765 +  }
   766 +
   767    return names;
   768  }
   770 -vector<string> DwarfCFIToModule::RegisterNames::I386() {
   771 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::I386() {
   772    static const char *const names[] = {
   773      "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
   774      "$eip", "$eflags", "$unused1",
   775      "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
   776      "$unused2", "$unused3",
   777      "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
   778      "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
   779      "$fcw", "$fsw", "$mxcsr",
   780      "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
   781      "$tr", "$ldtr"
   782    };
   784    return MakeVector(names, sizeof(names) / sizeof(names[0]));
   785  }
   787 -vector<string> DwarfCFIToModule::RegisterNames::X86_64() {
   788 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::X86_64() {
   789    static const char *const names[] = {
   790      "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
   791      "$r8",  "$r9",  "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
   792      "$rip",
   793      "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
   794      "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
   795      "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
   796      "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
   797 @@ -80,17 +84,17 @@
   798      "$tr", "$ldtr",
   799      "$mxcsr", "$fcw", "$fsw"
   800    };
   802    return MakeVector(names, sizeof(names) / sizeof(names[0]));
   803  }
   805  // Per ARM IHI 0040A, section 3.1
   806 -vector<string> DwarfCFIToModule::RegisterNames::ARM() {
   807 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::ARM() {
   808    static const char *const names[] = {
   809      "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
   810      "r8",  "r9",  "r10", "r11", "r12", "sp",  "lr",  "pc",
   811      "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
   812      "fps", "cpsr", "",   "",    "",    "",    "",    "",
   813      "",    "",    "",    "",    "",    "",    "",    "",
   814      "",    "",    "",    "",    "",    "",    "",    "",
   815      "",    "",    "",    "",    "",    "",    "",    "",
   816 @@ -122,40 +126,40 @@
   817    return_address_ = return_address;
   819    // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
   820    // may not establish any rule for .ra if the return address column
   821    // is an ordinary register, and that register holds the return
   822    // address on entry to the function. So establish an initial .ra
   823    // rule citing the return address register.
   824    if (return_address_ < register_names_.size())
   825 -    entry_->initial_rules[ra_name_]
   826 +    entry_->initial_rules[ustr__ZDra()]
   827        = Module::Expr(register_names_[return_address_], 0, false);
   829    return true;
   830  }
   832 -string DwarfCFIToModule::RegisterName(int i) {
   833 +const UniqueString* DwarfCFIToModule::RegisterName(int i) {
   834    assert(entry_);
   835    if (i < 0) {
   836      assert(i == kCFARegister);
   837 -    return cfa_name_;
   838 +    return ustr__ZDcfa();
   839    }
   840    unsigned reg = i;
   841    if (reg == return_address_)
   842 -    return ra_name_;
   843 +    return ustr__ZDra();
   845    // Ensure that a non-empty name exists for this register value.
   846 -  if (reg < register_names_.size() && !register_names_[reg].empty())
   847 +  if (reg < register_names_.size() && register_names_[reg] != ustr__empty())
   848      return register_names_[reg];
   850    reporter_->UnnamedRegister(entry_offset_, reg);
   851    char buf[30];
   852    sprintf(buf, "unnamed_register%u", reg);
   853 -  return buf;
   854 +  return ToUniqueString(buf);
   855  }
   857  void DwarfCFIToModule::Record(Module::Address address, int reg,
   858                                const Module::Expr &rule) {
   859    assert(entry_);
   861    // Is this one of this entry's initial rules?
   862    if (address == entry_->address)
   863 @@ -228,28 +232,30 @@
   865  void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
   866    fprintf(stderr, "%s, section '%s': "
   867            "the call frame entry at offset 0x%zx refers to register %d,"
   868            " whose name we don't know\n",
   869            file_.c_str(), section_.c_str(), offset, reg);
   870  }
   872 -void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset,
   873 -                                                       const string &reg) {
   874 +void DwarfCFIToModule::Reporter::UndefinedNotSupported(
   875 +    size_t offset,
   876 +    const UniqueString* reg) {
   877    fprintf(stderr, "%s, section '%s': "
   878            "the call frame entry at offset 0x%zx sets the rule for "
   879            "register '%s' to 'undefined', but the Breakpad symbol file format"
   880            " cannot express this\n",
   881 -          file_.c_str(), section_.c_str(), offset, reg.c_str());
   882 +          file_.c_str(), section_.c_str(), offset, FromUniqueString(reg));
   883  }
   885 -void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset,
   886 -                                                         const string &reg) {
   887 +void DwarfCFIToModule::Reporter::ExpressionsNotSupported(
   888 +    size_t offset,
   889 +    const UniqueString* reg) {
   890    fprintf(stderr, "%s, section '%s': "
   891            "the call frame entry at offset 0x%zx uses a DWARF expression to"
   892            " describe how to recover register '%s', "
   893            " but this translator cannot yet translate DWARF expressions to"
   894            " Breakpad postfix expressions\n",
   895 -          file_.c_str(), section_.c_str(), offset, reg.c_str());
   896 +          file_.c_str(), section_.c_str(), offset, FromUniqueString(reg));
   897  }
   899  } // namespace google_breakpad
   900 diff --git a/src/common/dwarf_cfi_to_module.h b/src/common/dwarf_cfi_to_module.h
   901 --- a/src/common/dwarf_cfi_to_module.h
   902 +++ b/src/common/dwarf_cfi_to_module.h
   903 @@ -44,16 +44,17 @@
   905  #include <set>
   906  #include <string>
   907  #include <vector>
   909  #include "common/module.h"
   910  #include "common/dwarf/dwarf2reader.h"
   911  #include "common/using_std_string.h"
   912 +#include "common/unique_string.h"
   914  namespace google_breakpad {
   916  using dwarf2reader::CallFrameInfo;
   917  using google_breakpad::Module;
   918  using std::set;
   919  using std::vector;
   921 @@ -78,61 +79,65 @@
   922      // The DWARF CFI entry at OFFSET cites register REG, but REG is not
   923      // covered by the vector of register names passed to the
   924      // DwarfCFIToModule constructor, nor does it match the return
   925      // address column number for this entry.
   926      virtual void UnnamedRegister(size_t offset, int reg);
   928      // The DWARF CFI entry at OFFSET says that REG is undefined, but the
   929      // Breakpad symbol file format cannot express this.
   930 -    virtual void UndefinedNotSupported(size_t offset, const string &reg);
   931 +    virtual void UndefinedNotSupported(size_t offset,
   932 +                                       const UniqueString* reg);
   934      // The DWARF CFI entry at OFFSET says that REG uses a DWARF
   935      // expression to find its value, but DwarfCFIToModule is not
   936      // capable of translating DWARF expressions to Breakpad postfix
   937      // expressions.
   938 -    virtual void ExpressionsNotSupported(size_t offset, const string &reg);
   939 +    virtual void ExpressionsNotSupported(size_t offset,
   940 +                                         const UniqueString* reg);
   942    protected:
   943      string file_, section_;
   944    };
   946    // Register name tables. If TABLE is a vector returned by one of these
   947    // functions, then TABLE[R] is the name of the register numbered R in
   948    // DWARF call frame information.
   949    class RegisterNames {
   950     public:
   951      // Intel's "x86" or IA-32.
   952 -    static vector<string> I386();
   953 +    static vector<const UniqueString*> I386();
   955      // AMD x86_64, AMD64, Intel EM64T, or Intel 64
   956 -    static vector<string> X86_64();
   957 +    static vector<const UniqueString*> X86_64();
   959      // ARM.
   960 -    static vector<string> ARM();
   961 +    static vector<const UniqueString*> ARM();
   963     private:
   964      // Given STRINGS, an array of C strings with SIZE elements, return an
   965      // equivalent vector<string>.
   966 -    static vector<string> MakeVector(const char * const *strings, size_t size);
   967 +    static vector<const UniqueString*> MakeVector(const char * const *strings,
   968 +                                                  size_t size);
   969    };
   971    // Create a handler for the dwarf2reader::CallFrameInfo parser that
   972    // records the stack unwinding information it receives in MODULE.
   973    //
   974    // Use REGISTER_NAMES[I] as the name of register number I; *this
   975    // keeps a reference to the vector, so the vector should remain
   976    // alive for as long as the DwarfCFIToModule does.
   977    //
   978    // Use REPORTER for reporting problems encountered in the conversion
   979    // process.
   980 -  DwarfCFIToModule(Module *module, const vector<string> &register_names,
   981 +  DwarfCFIToModule(Module *module,
   982 +                   const vector<const UniqueString*> &register_names,
   983                     Reporter *reporter)
   984        : module_(module), register_names_(register_names), reporter_(reporter),
   985 -        entry_(NULL), return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") {
   986 +        entry_(NULL), return_address_(-1) {
   987    }
   988    virtual ~DwarfCFIToModule() { delete entry_; }
   990    virtual bool Entry(size_t offset, uint64 address, uint64 length,
   991                       uint8 version, const string &augmentation,
   992                       unsigned return_address);
   993    virtual bool UndefinedRule(uint64 address, int reg);
   994    virtual bool SameValueRule(uint64 address, int reg);
   995 @@ -144,53 +149,36 @@
   996    virtual bool ExpressionRule(uint64 address, int reg,
   997                                const string &expression);
   998    virtual bool ValExpressionRule(uint64 address, int reg,
   999                                   const string &expression);
  1000    virtual bool End();
  1002   private:
  1003    // Return the name to use for register REG.
  1004 -  string RegisterName(int i);
  1005 +  const UniqueString* RegisterName(int i);
  1007    // Record RULE for register REG at ADDRESS.
  1008    void Record(Module::Address address, int reg, const Module::Expr &rule);
  1010    // The module to which we should add entries.
  1011    Module *module_;
  1013    // Map from register numbers to register names.
  1014 -  const vector<string> &register_names_;
  1015 +  const vector<const UniqueString*> &register_names_;
  1017    // The reporter to use to report problems.
  1018    Reporter *reporter_;
  1020    // The current entry we're constructing.
  1021    Module::StackFrameEntry *entry_;
  1023    // The section offset of the current frame description entry, for
  1024    // use in error messages.
  1025    size_t entry_offset_;
  1027    // The return address column for that entry.
  1028    unsigned return_address_;
  1030 -  // The names of the return address and canonical frame address. Putting
  1031 -  // these here instead of using string literals allows us to share their
  1032 -  // texts in reference-counted std::string implementations (all the
  1033 -  // popular ones). Many, many rules cite these strings.
  1034 -  string cfa_name_, ra_name_;
  1036 -  // A set of strings used by this CFI. Before storing a string in one of
  1037 -  // our data structures, insert it into this set, and then use the string
  1038 -  // from the set.
  1039 -  // 
  1040 -  // Because std::string uses reference counting internally, simply using
  1041 -  // strings from this set, even if passed by value, assigned, or held
  1042 -  // directly in structures and containers (map<string, ...>, for example),
  1043 -  // causes those strings to share a single instance of each distinct piece
  1044 -  // of text.
  1045 -  set<string> common_strings_;
  1046  };
  1048  } // namespace google_breakpad
  1050  #endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H
  1051 diff --git a/src/common/dwarf_cfi_to_module_unittest.cc b/src/common/dwarf_cfi_to_module_unittest.cc
  1052 --- a/src/common/dwarf_cfi_to_module_unittest.cc
  1053 +++ b/src/common/dwarf_cfi_to_module_unittest.cc
  1054 @@ -37,52 +37,59 @@
  1055  #include "breakpad_googletest_includes.h"
  1056  #include "common/dwarf_cfi_to_module.h"
  1057  #include "common/using_std_string.h"
  1059  using std::vector;
  1061  using google_breakpad::Module;
  1062  using google_breakpad::DwarfCFIToModule;
  1063 +using google_breakpad::ToUniqueString;
  1064 +using google_breakpad::UniqueString;
  1065 +using google_breakpad::ustr__ZDcfa;
  1066 +using google_breakpad::ustr__ZDra;
  1067 +using google_breakpad::ustr__empty;
  1068  using testing::ContainerEq;
  1069  using testing::Test;
  1070  using testing::_;
  1072  struct MockCFIReporter: public DwarfCFIToModule::Reporter {
  1073    MockCFIReporter(const string &file, const string &section)
  1074        : Reporter(file, section) { }
  1075    MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg));
  1076 -  MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string &reg));
  1077 -  MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string &reg));
  1078 +  MOCK_METHOD2(UndefinedNotSupported, void(size_t offset,
  1079 +                                           const UniqueString* reg));
  1080 +  MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset,
  1081 +                                             const UniqueString* reg));
  1082  };
  1084  struct DwarfCFIToModuleFixture {
  1085    DwarfCFIToModuleFixture()
  1086        : module("module name", "module os", "module arch", "module id"),
  1087          reporter("reporter file", "reporter section"),
  1088          handler(&module, register_names, &reporter) {
  1089 -    register_names.push_back("reg0");
  1090 -    register_names.push_back("reg1");
  1091 -    register_names.push_back("reg2");
  1092 -    register_names.push_back("reg3");
  1093 -    register_names.push_back("reg4");
  1094 -    register_names.push_back("reg5");
  1095 -    register_names.push_back("reg6");
  1096 -    register_names.push_back("reg7");
  1097 -    register_names.push_back("sp");
  1098 -    register_names.push_back("pc");
  1099 -    register_names.push_back("");
  1100 +    register_names.push_back(ToUniqueString("reg0"));
  1101 +    register_names.push_back(ToUniqueString("reg1"));
  1102 +    register_names.push_back(ToUniqueString("reg2"));
  1103 +    register_names.push_back(ToUniqueString("reg3"));
  1104 +    register_names.push_back(ToUniqueString("reg4"));
  1105 +    register_names.push_back(ToUniqueString("reg5"));
  1106 +    register_names.push_back(ToUniqueString("reg6"));
  1107 +    register_names.push_back(ToUniqueString("reg7"));
  1108 +    register_names.push_back(ToUniqueString("sp"));
  1109 +    register_names.push_back(ToUniqueString("pc"));
  1110 +    register_names.push_back(ustr__empty());
  1112      EXPECT_CALL(reporter, UnnamedRegister(_, _)).Times(0);
  1113      EXPECT_CALL(reporter, UndefinedNotSupported(_, _)).Times(0);
  1114      EXPECT_CALL(reporter, ExpressionsNotSupported(_, _)).Times(0);
  1117    Module module;
  1118 -  vector<string> register_names;
  1119 +  vector<const UniqueString*> register_names;
  1120    MockCFIReporter reporter;
  1121    DwarfCFIToModule handler;
  1122    vector<Module::StackFrameEntry *> entries;
  1123  };
  1125  class Entry: public DwarfCFIToModuleFixture, public Test { };
  1127  TEST_F(Entry, Accept) {
  1128 @@ -127,183 +134,190 @@
  1130    uint64 entry_address, entry_size;
  1131    unsigned return_reg;
  1132  };
  1134  class Rule: public RuleFixture, public Test { };
  1136  TEST_F(Rule, UndefinedRule) {
  1137 -  EXPECT_CALL(reporter, UndefinedNotSupported(_, "reg7"));
  1138 +  EXPECT_CALL(reporter, UndefinedNotSupported(_, ToUniqueString("reg7")));
  1139    StartEntry();
  1140    ASSERT_TRUE(handler.UndefinedRule(entry_address, 7));
  1141    ASSERT_TRUE(handler.End());
  1142    CheckEntry();
  1143    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1144    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1147  TEST_F(Rule, RegisterWithEmptyName) {
  1148    EXPECT_CALL(reporter, UnnamedRegister(_, 10));
  1149 -  EXPECT_CALL(reporter, UndefinedNotSupported(_, "unnamed_register10"));
  1150 +  EXPECT_CALL(reporter,
  1151 +              UndefinedNotSupported(_, ToUniqueString("unnamed_register10")));
  1152    StartEntry();
  1153    ASSERT_TRUE(handler.UndefinedRule(entry_address, 10));
  1154    ASSERT_TRUE(handler.End());
  1155    CheckEntry();
  1156    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1157    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1160  TEST_F(Rule, SameValueRule) {
  1161    StartEntry();
  1162    ASSERT_TRUE(handler.SameValueRule(entry_address, 6));
  1163    ASSERT_TRUE(handler.End());
  1164    CheckEntry();
  1165    Module::RuleMap expected_initial;
  1166 -  expected_initial["reg6"] = Module::Expr("reg6", 0, false);
  1167 +  const UniqueString* reg6 = ToUniqueString("reg6");
  1168 +  expected_initial[reg6] = Module::Expr(reg6, 0, false);
  1169    EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
  1170    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1173  TEST_F(Rule, OffsetRule) {
  1174    StartEntry();
  1175    ASSERT_TRUE(handler.OffsetRule(entry_address + 1, return_reg,
  1176                                   DwarfCFIToModule::kCFARegister,
  1177                                   16927065));
  1178    ASSERT_TRUE(handler.End());
  1179    CheckEntry();
  1180    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1181    Module::RuleChangeMap expected_changes;
  1182 -  expected_changes[entry_address + 1][".ra"] =
  1183 -      Module::Expr(".cfa", 16927065, true);
  1184 +  expected_changes[entry_address + 1][ustr__ZDra()] =
  1185 +      Module::Expr(ustr__ZDcfa(), 16927065, true);
  1186    EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
  1189  TEST_F(Rule, OffsetRuleNegative) {
  1190    StartEntry();
  1191    ASSERT_TRUE(handler.OffsetRule(entry_address + 1,
  1192                                   DwarfCFIToModule::kCFARegister, 4, -34530721));
  1193    ASSERT_TRUE(handler.End());
  1194    CheckEntry();
  1195    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1196    Module::RuleChangeMap expected_changes;
  1197 -  expected_changes[entry_address + 1][".cfa"] =
  1198 -      Module::Expr("reg4", -34530721, true);
  1199 +  expected_changes[entry_address + 1][ustr__ZDcfa()] =
  1200 +      Module::Expr(ToUniqueString("reg4"), -34530721, true);
  1201    EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
  1204  TEST_F(Rule, ValOffsetRule) {
  1205    // Use an unnamed register number, to exercise that branch of RegisterName.
  1206    EXPECT_CALL(reporter, UnnamedRegister(_, 11));
  1207    StartEntry();
  1208    ASSERT_TRUE(handler.ValOffsetRule(entry_address + 0x5ab7,
  1209                                      DwarfCFIToModule::kCFARegister,
  1210                                      11, 61812979));
  1211    ASSERT_TRUE(handler.End());
  1212    CheckEntry();
  1213    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1214    Module::RuleChangeMap expected_changes;
  1215 -  expected_changes[entry_address + 0x5ab7][".cfa"] =
  1216 -      Module::Expr("unnamed_register11", 61812979, false);
  1217 +  expected_changes[entry_address + 0x5ab7][ustr__ZDcfa()] =
  1218 +      Module::Expr(ToUniqueString("unnamed_register11"), 61812979, false);
  1219    EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
  1222  TEST_F(Rule, RegisterRule) {
  1223    StartEntry();
  1224    ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 3));
  1225    ASSERT_TRUE(handler.End());
  1226    CheckEntry();
  1227    Module::RuleMap expected_initial;
  1228 -  expected_initial[".ra"] = Module::Expr("reg3", 0, false);
  1229 +  expected_initial[ustr__ZDra()] =
  1230 +      Module::Expr(ToUniqueString("reg3"), 0, false);
  1231    EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
  1232    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1235  TEST_F(Rule, ExpressionRule) {
  1236 -  EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg2"));
  1237 +  EXPECT_CALL(reporter, ExpressionsNotSupported(_, ToUniqueString("reg2")));
  1238    StartEntry();
  1239    ASSERT_TRUE(handler.ExpressionRule(entry_address + 0xf326, 2,
  1240                                       "it takes two to tango"));
  1241    ASSERT_TRUE(handler.End());
  1242    CheckEntry();
  1243    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1244    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1247  TEST_F(Rule, ValExpressionRule) {
  1248 -  EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg0"));
  1249 +  EXPECT_CALL(reporter, ExpressionsNotSupported(_, ToUniqueString("reg0")));
  1250    StartEntry();
  1251    ASSERT_TRUE(handler.ValExpressionRule(entry_address + 0x6367, 0,
  1252                                          "bit off more than he could chew"));
  1253    ASSERT_TRUE(handler.End());
  1254    CheckEntry();
  1255    EXPECT_EQ(0U, entries[0]->initial_rules.size());
  1256    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1259  TEST_F(Rule, DefaultReturnAddressRule) {
  1260    return_reg = 2;
  1261    StartEntry();
  1262    ASSERT_TRUE(handler.RegisterRule(entry_address, 0, 1));
  1263    ASSERT_TRUE(handler.End());
  1264    CheckEntry();
  1265    Module::RuleMap expected_initial;
  1266 -  expected_initial[".ra"] = Module::Expr("reg2", 0, false);
  1267 -  expected_initial["reg0"] = Module::Expr("reg1", 0, false);
  1268 +  expected_initial[ustr__ZDra()] =
  1269 +      Module::Expr(ToUniqueString("reg2"), 0, false);
  1270 +  expected_initial[ToUniqueString("reg0")] =
  1271 +      Module::Expr(ToUniqueString("reg1"), 0, false);
  1272    EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
  1273    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1276  TEST_F(Rule, DefaultReturnAddressRuleOverride) {
  1277    return_reg = 2;
  1278    StartEntry();
  1279    ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 1));
  1280    ASSERT_TRUE(handler.End());
  1281    CheckEntry();
  1282    Module::RuleMap expected_initial;
  1283 -  expected_initial[".ra"] = Module::Expr("reg1", 0, false);
  1284 +  expected_initial[ustr__ZDra()] =
  1285 +      Module::Expr(ToUniqueString("reg1"), 0, false);
  1286    EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
  1287    EXPECT_EQ(0U, entries[0]->rule_changes.size());
  1290  TEST_F(Rule, DefaultReturnAddressRuleLater) {
  1291    return_reg = 2;
  1292    StartEntry();
  1293    ASSERT_TRUE(handler.RegisterRule(entry_address + 1, return_reg, 1));
  1294    ASSERT_TRUE(handler.End());
  1295    CheckEntry();
  1296    Module::RuleMap expected_initial;
  1297 -  expected_initial[".ra"] = Module::Expr("reg2", 0, false);
  1298 +  expected_initial[ustr__ZDra()] =
  1299 +      Module::Expr(ToUniqueString("reg2"), 0, false);
  1300    EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
  1301    Module::RuleChangeMap expected_changes;
  1302 -  expected_changes[entry_address + 1][".ra"] =
  1303 -      Module::Expr("reg1", 0, false);
  1304 +  expected_changes[entry_address + 1][ustr__ZDra()] =
  1305 +      Module::Expr(ToUniqueString("reg1"), 0, false);
  1306    EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
  1309  TEST(RegisterNames, I386) {
  1310 -  vector<string> names = DwarfCFIToModule::RegisterNames::I386();
  1311 +  vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::I386();
  1313 -  EXPECT_EQ("$eax", names[0]);
  1314 -  EXPECT_EQ("$ecx", names[1]);
  1315 -  EXPECT_EQ("$esp", names[4]);
  1316 -  EXPECT_EQ("$eip", names[8]);
  1317 +  EXPECT_EQ(ToUniqueString("$eax"), names[0]);
  1318 +  EXPECT_EQ(ToUniqueString("$ecx"), names[1]);
  1319 +  EXPECT_EQ(ToUniqueString("$esp"), names[4]);
  1320 +  EXPECT_EQ(ToUniqueString("$eip"), names[8]);
  1323  TEST(RegisterNames, ARM) {
  1324 -  vector<string> names = DwarfCFIToModule::RegisterNames::ARM();
  1325 +  vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::ARM();
  1327 -  EXPECT_EQ("r0", names[0]);
  1328 -  EXPECT_EQ("r10", names[10]);
  1329 -  EXPECT_EQ("sp", names[13]);
  1330 -  EXPECT_EQ("lr", names[14]);
  1331 -  EXPECT_EQ("pc", names[15]);
  1332 +  EXPECT_EQ(ToUniqueString("r0"), names[0]);
  1333 +  EXPECT_EQ(ToUniqueString("r10"), names[10]);
  1334 +  EXPECT_EQ(ToUniqueString("sp"), names[13]);
  1335 +  EXPECT_EQ(ToUniqueString("lr"), names[14]);
  1336 +  EXPECT_EQ(ToUniqueString("pc"), names[15]);
  1339  TEST(RegisterNames, X86_64) {
  1340 -  vector<string> names = DwarfCFIToModule::RegisterNames::X86_64();
  1341 +  vector<const UniqueString*> names = DwarfCFIToModule::RegisterNames::X86_64();
  1343 -  EXPECT_EQ("$rax", names[0]);
  1344 -  EXPECT_EQ("$rdx", names[1]);
  1345 -  EXPECT_EQ("$rbp", names[6]);
  1346 -  EXPECT_EQ("$rsp", names[7]);
  1347 -  EXPECT_EQ("$rip", names[16]);
  1348 +  EXPECT_EQ(ToUniqueString("$rax"), names[0]);
  1349 +  EXPECT_EQ(ToUniqueString("$rdx"), names[1]);
  1350 +  EXPECT_EQ(ToUniqueString("$rbp"), names[6]);
  1351 +  EXPECT_EQ(ToUniqueString("$rsp"), names[7]);
  1352 +  EXPECT_EQ(ToUniqueString("$rip"), names[16]);
  1354 diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
  1355 --- a/src/common/linux/dump_symbols.cc
  1356 +++ b/src/common/linux/dump_symbols.cc
  1357 @@ -81,16 +81,17 @@
  1358  using google_breakpad::ElfClass64;
  1359  using google_breakpad::FindElfSectionByName;
  1360  using google_breakpad::GetOffset;
  1361  using google_breakpad::IsValidElf;
  1362  using google_breakpad::Module;
  1363  #ifndef NO_STABS_SUPPORT
  1364  using google_breakpad::StabsToModule;
  1365  #endif
  1366 +using google_breakpad::UniqueString;
  1367  using google_breakpad::scoped_ptr;
  1369  //
  1370  // FDWrapper
  1371  //
  1372  // Wrapper class to make sure opened file is closed.
  1373  //
  1374  class FDWrapper {
  1375 @@ -278,17 +279,17 @@
  1377  // Fill REGISTER_NAMES with the register names appropriate to the
  1378  // machine architecture given in HEADER, indexed by the register
  1379  // numbers used in DWARF call frame information. Return true on
  1380  // success, or false if HEADER's machine architecture is not
  1381  // supported.
  1382  template<typename ElfClass>
  1383  bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
  1384 -                           std::vector<string>* register_names) {
  1385 +                           std::vector<const UniqueString*>* register_names) {
  1386    switch (elf_header->e_machine) {
  1387      case EM_386:
  1388        *register_names = DwarfCFIToModule::RegisterNames::I386();
  1389        return true;
  1390      case EM_ARM:
  1391        *register_names = DwarfCFIToModule::RegisterNames::ARM();
  1392        return true;
  1393      case EM_X86_64:
  1394 @@ -306,17 +307,17 @@
  1395                    const typename ElfClass::Shdr* section,
  1396                    const bool eh_frame,
  1397                    const typename ElfClass::Shdr* got_section,
  1398                    const typename ElfClass::Shdr* text_section,
  1399                    const bool big_endian,
  1400                    Module* module) {
  1401    // Find the appropriate set of register names for this file's
  1402    // architecture.
  1403 -  std::vector<string> register_names;
  1404 +  std::vector<const UniqueString*> register_names;
  1405    if (!DwarfCFIRegisterNames<ElfClass>(elf_header, &register_names)) {
  1406      fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';"
  1407              " cannot convert DWARF call frame information\n",
  1408              dwarf_filename.c_str(), elf_header->e_machine);
  1409      return false;
  1412    const dwarf2reader::Endianness endianness = big_endian ?
  1413 diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.mm
  1414 --- a/src/common/mac/dump_syms.mm
  1415 +++ b/src/common/mac/dump_syms.mm
  1416 @@ -313,17 +313,17 @@
  1419  bool DumpSymbols::ReadCFI(google_breakpad::Module *module,
  1420                            const mach_o::Reader &macho_reader,
  1421                            const mach_o::Section &section,
  1422                            bool eh_frame) const {
  1423    // Find the appropriate set of register names for this file's
  1424    // architecture.
  1425 -  vector<string> register_names;
  1426 +  vector<const UniqueString*> register_names;
  1427    switch (macho_reader.cpu_type()) {
  1428      case CPU_TYPE_X86:
  1429        register_names = DwarfCFIToModule::RegisterNames::I386();
  1430        break;
  1431      case CPU_TYPE_X86_64:
  1432        register_names = DwarfCFIToModule::RegisterNames::X86_64();
  1433        break;
  1434      case CPU_TYPE_ARM:
  1435 diff --git a/src/common/module.cc b/src/common/module.cc
  1436 --- a/src/common/module.cc
  1437 +++ b/src/common/module.cc
  1438 @@ -33,16 +33,17 @@
  1440  #include "common/module.h"
  1442  #include <assert.h>
  1443  #include <errno.h>
  1444  #include <stdio.h>
  1445  #include <string.h>
  1447 +#include <algorithm>
  1448  #include <iostream>
  1449  #include <utility>
  1451  namespace google_breakpad {
  1453  using std::dec;
  1454  using std::endl;
  1455  using std::hex;
  1456 @@ -255,36 +256,50 @@
  1457            strerror(errno));
  1458    return false;
  1461  std::ostream& operator<<(std::ostream& stream, const Module::Expr& expr) {
  1462    assert(!expr.invalid());
  1463    switch (expr.how_) {
  1464      case Module::kExprSimple:
  1465 -      stream << expr.ident_ << " " << expr.offset_ << " +";
  1466 +      stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " +";
  1467        break;
  1468      case Module::kExprSimpleMem:
  1469 -      stream << expr.ident_ << " " << expr.offset_ << " + ^";
  1470 +      stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " + ^";
  1471        break;
  1472      case Module::kExprPostfix:
  1473        stream << expr.postfix_; break;
  1474      case Module::kExprInvalid:
  1475      default:
  1476        break;
  1478    return stream;
  1481  bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) {
  1482 +  // Visit the register rules in alphabetical order.  Because
  1483 +  // rule_map has the elements in some arbitrary order,
  1484 +  // get the names out into a vector, sort them, and visit in
  1485 +  // sorted order.
  1486 +  std::vector<const UniqueString*> rr_names;
  1487    for (RuleMap::const_iterator it = rule_map.begin();
  1488         it != rule_map.end(); ++it) {
  1489 -    if (it != rule_map.begin())
  1490 -      stream << ' ';
  1491 -    stream << it->first << ": " << it->second;
  1492 +    rr_names.push_back(it->first);
  1493 +  }
  1495 +  std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString);
  1497 +  // Now visit the register rules in alphabetical order.
  1498 +  for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin();
  1499 +       name != rr_names.end();
  1500 +       ++name) {
  1501 +    if (name != rr_names.begin())
  1502 +      stream << " ";
  1503 +    stream << FromUniqueString(*name) << ": " << rule_map.find(*name)->second;
  1505    return stream.good();
  1508  bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
  1509    stream << "MODULE " << os_ << " " << architecture_ << " "
  1510           << id_ << " " << name_ << endl;
  1511    if (!stream.good())
  1512 diff --git a/src/common/module.h b/src/common/module.h
  1513 --- a/src/common/module.h
  1514 +++ b/src/common/module.h
  1515 @@ -41,16 +41,17 @@
  1516  #include <iostream>
  1517  #include <map>
  1518  #include <set>
  1519  #include <string>
  1520  #include <vector>
  1522  #include "common/symbol_data.h"
  1523  #include "common/using_std_string.h"
  1524 +#include "common/unique_string.h"
  1525  #include "google_breakpad/common/breakpad_types.h"
  1527  namespace google_breakpad {
  1529  using std::set;
  1530  using std::vector;
  1531  using std::map;
  1533 @@ -131,69 +132,69 @@
  1534    enum ExprHow {
  1535      kExprInvalid = 1,
  1536      kExprPostfix,
  1537      kExprSimple,
  1538      kExprSimpleMem
  1539    };
  1540    struct Expr {
  1541      // Construct a simple-form expression
  1542 -    Expr(string ident, long offset, bool deref) {
  1543 -      if (ident.empty()) {
  1544 +    Expr(const UniqueString* ident, long offset, bool deref) {
  1545 +      if (ident == ustr__empty()) {
  1546          Expr();
  1547        } else {
  1548          postfix_ = "";
  1549          ident_ = ident;
  1550          offset_ = offset;
  1551          how_ = deref ? kExprSimpleMem : kExprSimple;
  1554      // Construct an expression from a postfix string
  1555      Expr(string postfix) {
  1556        if (postfix.empty()) {
  1557          Expr();
  1558        } else {
  1559          postfix_ = postfix;
  1560 -        ident_ = "";
  1561 +        ident_ = NULL;
  1562          offset_ = 0;
  1563          how_ = kExprPostfix;
  1566      // Construct an invalid expression
  1567      Expr() {
  1568        postfix_ = "";
  1569 -      ident_ = "";
  1570 +      ident_ = NULL;
  1571        offset_ = 0;
  1572        how_ = kExprInvalid;
  1574      bool invalid() const { return how_ == kExprInvalid; }
  1575      bool operator==(const Expr& other) const {
  1576        return how_ == other.how_ &&
  1577            ident_ == other.ident_ &&
  1578            offset_ == other.offset_ &&
  1579            postfix_ == other.postfix_;
  1582      // The identifier that gives the starting value for simple expressions.
  1583 -    string  ident_;
  1584 +    const UniqueString* ident_;
  1585      // The offset to add for simple expressions.
  1586      long    offset_;
  1587      // The Postfix expression string to evaluate for non-simple expressions.
  1588      string  postfix_;
  1589      // The operation expressed by this expression.
  1590      ExprHow how_;
  1592      friend std::ostream& operator<<(std::ostream& stream, const Expr& expr);
  1593    };
  1595    // A map from register names to expressions that recover
  1596    // their values. This can represent a complete set of rules to
  1597    // follow at some address, or a set of changes to be applied to an
  1598    // extant set of rules.
  1599 -  typedef map<string, Expr> RuleMap;
  1600 +  typedef map<const UniqueString*, Expr> RuleMap;
  1602    // A map from addresses to RuleMaps, representing changes that take
  1603    // effect at given addresses.
  1604    typedef map<Address, RuleMap> RuleChangeMap;
  1606    // A range of 'STACK CFI' stack walking information. An instance of
  1607    // this structure corresponds to a 'STACK CFI INIT' record and the
  1608    // subsequent 'STACK CFI' records that fall within its range.
  1609 diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
  1610 --- a/src/common/module_unittest.cc
  1611 +++ b/src/common/module_unittest.cc
  1612 @@ -40,16 +40,18 @@
  1613  #include <sstream>
  1614  #include <string>
  1616  #include "breakpad_googletest_includes.h"
  1617  #include "common/module.h"
  1618  #include "common/using_std_string.h"
  1620  using google_breakpad::Module;
  1621 +using google_breakpad::ToUniqueString;
  1622 +using google_breakpad::ustr__ZDcfa;
  1623  using std::stringstream;
  1624  using std::vector;
  1625  using testing::ContainerEq;
  1627  static Module::Function *generate_duplicate_function(const string &name) {
  1628    const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL;
  1629    const Module::Address DUP_SIZE = 0x200b26e605f99071LL;
  1630    const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
  1631 @@ -125,21 +127,27 @@
  1632    function->lines.push_back(line1);
  1634    m.AddFunction(function);
  1636    // Some stack information.
  1637    Module::StackFrameEntry *entry = new Module::StackFrameEntry();
  1638    entry->address = 0x30f9e5c83323973dULL;
  1639    entry->size = 0x49fc9ca7c7c13dc2ULL;
  1640 -  entry->initial_rules[".cfa"] = Module::Expr("he was a handsome man");
  1641 -  entry->initial_rules["and"] = Module::Expr("what i want to know is");
  1642 -  entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
  1643 -    Module::Expr("do you like your blueeyed boy");
  1644 -  entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = Module::Expr("Death");
  1645 +  entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man");
  1646 +  entry->initial_rules[ToUniqueString("and")] =
  1647 +      Module::Expr("what i want to know is");
  1648 +  entry->initial_rules[ToUniqueString("stallion")] =
  1649 +      Module::Expr(ToUniqueString("and break"), 8, false);
  1650 +  entry->initial_rules[ToUniqueString("onetwothreefourfive")] =
  1651 +      Module::Expr(ToUniqueString("pigeonsjustlikethat"), 42, true);
  1652 +  entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] =
  1653 +      Module::Expr("do you like your blueeyed boy");
  1654 +  entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] =
  1655 +      Module::Expr("Death");
  1656    m.AddStackFrameEntry(entry);
  1658    // Set the load address.  Doing this after adding all the data to
  1659    // the module must work fine.
  1660    m.SetLoadAddress(0x2ab698b0b6407073LL);
  1662    m.Write(s, ALL_SYMBOL_DATA);
  1663    string contents = s.str();
  1664 @@ -147,17 +155,19 @@
  1665                 "FILE 0 filename-a.cc\n"
  1666                 "FILE 1 filename-b.cc\n"
  1667                 "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
  1668                 " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
  1669                 "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n"
  1670                 "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n"
  1671                 "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2"
  1672                 " .cfa: he was a handsome man"
  1673 -               " and: what i want to know is\n"
  1674 +               " and: what i want to know is"
  1675 +               " onetwothreefourfive: pigeonsjustlikethat 42 + ^"
  1676 +               " stallion: and break 8 +\n"
  1677                 "STACK CFI 6434d177ce326cb"
  1678                 " Mister: Death"
  1679                 " how: do you like your blueeyed boy\n",
  1680                 contents.c_str());
  1683  TEST(Write, OmitUnusedFiles) {
  1684    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
  1685 @@ -229,21 +239,23 @@
  1686    function->lines.push_back(line1);
  1688    m.AddFunction(function);
  1690    // Some stack information.
  1691    Module::StackFrameEntry *entry = new Module::StackFrameEntry();
  1692    entry->address = 0x30f9e5c83323973dULL;
  1693    entry->size = 0x49fc9ca7c7c13dc2ULL;
  1694 -  entry->initial_rules[".cfa"] = Module::Expr("he was a handsome man");
  1695 -  entry->initial_rules["and"] = Module::Expr("what i want to know is");
  1696 -  entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
  1697 -    Module::Expr("do you like your blueeyed boy");
  1698 -  entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = Module::Expr("Death");
  1699 +  entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man");
  1700 +  entry->initial_rules[ToUniqueString("and")] =
  1701 +      Module::Expr("what i want to know is");
  1702 +  entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] =
  1703 +      Module::Expr("do you like your blueeyed boy");
  1704 +  entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] =
  1705 +      Module::Expr("Death");
  1706    m.AddStackFrameEntry(entry);
  1708    // Set the load address.  Doing this after adding all the data to
  1709    // the module must work fine.
  1710    m.SetLoadAddress(0x2ab698b0b6407073LL);
  1712    m.Write(s, NO_CFI);
  1713    string contents = s.str();
  1714 @@ -305,33 +317,36 @@
  1715    entry1->address = 0xddb5f41285aa7757ULL;
  1716    entry1->size = 0x1486493370dc5073ULL;
  1717    m.AddStackFrameEntry(entry1);
  1719    // Second STACK CFI entry, with initial rules but no deltas.
  1720    Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
  1721    entry2->address = 0x8064f3af5e067e38ULL;
  1722    entry2->size = 0x0de2a5ee55509407ULL;
  1723 -  entry2->initial_rules[".cfa"] = Module::Expr("I think that I shall never see");
  1724 -  entry2->initial_rules["stromboli"] = Module::Expr("a poem lovely as a tree");
  1725 -  entry2->initial_rules["cannoli"] = Module::Expr("a tree whose hungry mouth is prest");
  1726 +  entry2->initial_rules[ustr__ZDcfa()] =
  1727 +      Module::Expr("I think that I shall never see");
  1728 +  entry2->initial_rules[ToUniqueString("stromboli")] =
  1729 +      Module::Expr("a poem lovely as a tree");
  1730 +  entry2->initial_rules[ToUniqueString("cannoli")] =
  1731 +      Module::Expr("a tree whose hungry mouth is prest");
  1732    m.AddStackFrameEntry(entry2);
  1734    // Third STACK CFI entry, with initial rules and deltas.
  1735    Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
  1736    entry3->address = 0x5e8d0db0a7075c6cULL;
  1737    entry3->size = 0x1c7edb12a7aea229ULL;
  1738 -  entry3->initial_rules[".cfa"] = Module::Expr("Whose woods are these");
  1739 -  entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
  1740 +  entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
  1741 +  entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
  1742      Module::Expr("the village though");
  1743 -  entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
  1744 +  entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
  1745      Module::Expr("he will not see me stopping here");
  1746 -  entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
  1747 +  entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
  1748      Module::Expr("his house is in");
  1749 -  entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
  1750 +  entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
  1751      Module::Expr("I think I know");
  1752    m.AddStackFrameEntry(entry3);
  1754    // Check that Write writes STACK CFI records properly.
  1755    m.Write(s, ALL_SYMBOL_DATA);
  1756    string contents = s.str();
  1757    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
  1758                 "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
  1759 @@ -352,33 +367,39 @@
  1760    // Check that GetStackFrameEntries works.
  1761    vector<Module::StackFrameEntry *> entries;
  1762    m.GetStackFrameEntries(&entries);
  1763    ASSERT_EQ(3U, entries.size());
  1764    // Check first entry.
  1765    EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address);
  1766    EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size);
  1767    Module::RuleMap entry1_initial;
  1768 -  entry1_initial[".cfa"] = Module::Expr("Whose woods are these");
  1769 +  entry1_initial[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
  1770    EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial));
  1771    Module::RuleChangeMap entry1_changes;
  1772 -  entry1_changes[0x36682fad3763ffffULL][".cfa"] = Module::Expr("I think I know");
  1773 -  entry1_changes[0x36682fad3763ffffULL]["stromboli"] = Module::Expr("his house is in");
  1774 -  entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = Module::Expr("the village though");
  1775 -  entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
  1776 -    Module::Expr("he will not see me stopping here");
  1777 +  entry1_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
  1778 +      Module::Expr("I think I know");
  1779 +  entry1_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
  1780 +      Module::Expr("his house is in");
  1781 +  entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
  1782 +      Module::Expr("the village though");
  1783 +  entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
  1784 +      Module::Expr("he will not see me stopping here");
  1785    EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes));
  1786    // Check second entry.
  1787    EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
  1788    EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
  1789    ASSERT_EQ(3U, entries[1]->initial_rules.size());
  1790    Module::RuleMap entry2_initial;
  1791 -  entry2_initial[".cfa"] = Module::Expr("I think that I shall never see");
  1792 -  entry2_initial["stromboli"] = Module::Expr("a poem lovely as a tree");
  1793 -  entry2_initial["cannoli"] = Module::Expr("a tree whose hungry mouth is prest");
  1794 +  entry2_initial[ustr__ZDcfa()] =
  1795 +      Module::Expr("I think that I shall never see");
  1796 +  entry2_initial[ToUniqueString("stromboli")] =
  1797 +      Module::Expr("a poem lovely as a tree");
  1798 +  entry2_initial[ToUniqueString("cannoli")] =
  1799 +      Module::Expr("a tree whose hungry mouth is prest");
  1800    EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
  1801    ASSERT_EQ(0U, entries[1]->rule_changes.size());
  1802    // Check third entry.
  1803    EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address);
  1804    EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size);
  1805    ASSERT_EQ(0U, entries[2]->initial_rules.size());
  1806    ASSERT_EQ(0U, entries[2]->rule_changes.size());
  1808 @@ -585,33 +606,36 @@
  1809    entry1->address = 0x2000;
  1810    entry1->size = 0x900;
  1811    m.AddStackFrameEntry(entry1);
  1813    // Second STACK CFI entry, with initial rules but no deltas.
  1814    Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
  1815    entry2->address = 0x3000;
  1816    entry2->size = 0x900;
  1817 -  entry2->initial_rules[".cfa"] = Module::Expr("I think that I shall never see");
  1818 -  entry2->initial_rules["stromboli"] = Module::Expr("a poem lovely as a tree");
  1819 -  entry2->initial_rules["cannoli"] = Module::Expr("a tree whose hungry mouth is prest");
  1820 +  entry2->initial_rules[ustr__ZDcfa()] =
  1821 +      Module::Expr("I think that I shall never see");
  1822 +  entry2->initial_rules[ToUniqueString("stromboli")] =
  1823 +      Module::Expr("a poem lovely as a tree");
  1824 +  entry2->initial_rules[ToUniqueString("cannoli")] =
  1825 +      Module::Expr("a tree whose hungry mouth is prest");
  1826    m.AddStackFrameEntry(entry2);
  1828    // Third STACK CFI entry, with initial rules and deltas.
  1829    Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
  1830    entry3->address = 0x1000;
  1831    entry3->size = 0x900;
  1832 -  entry3->initial_rules[".cfa"] = Module::Expr("Whose woods are these");
  1833 -  entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
  1834 +  entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
  1835 +  entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
  1836      Module::Expr("the village though");
  1837 -  entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
  1838 +  entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
  1839      Module::Expr("he will not see me stopping here");
  1840 -  entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
  1841 +  entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
  1842      Module::Expr("his house is in");
  1843 -  entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
  1844 +  entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
  1845      Module::Expr("I think I know");
  1846    m.AddStackFrameEntry(entry3);
  1848    Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000);
  1849    EXPECT_EQ(entry3, s);
  1850    s = m.FindStackFrameEntryByAddress(0x18FF);
  1851    EXPECT_EQ(entry3, s);
  1853 diff --git a/src/common/unique_string.cc b/src/common/unique_string.cc
  1854 new file mode 100644
  1855 --- /dev/null
  1856 +++ b/src/common/unique_string.cc
  1857 @@ -0,0 +1,110 @@
  1858 +// Copyright (c) 2013 Google Inc.
  1859 +// All rights reserved.
  1860 +//
  1861 +// Redistribution and use in source and binary forms, with or without
  1862 +// modification, are permitted provided that the following conditions are
  1863 +// met:
  1864 +//
  1865 +//     * Redistributions of source code must retain the above copyright
  1866 +// notice, this list of conditions and the following disclaimer.
  1867 +//     * Redistributions in binary form must reproduce the above
  1868 +// copyright notice, this list of conditions and the following disclaimer
  1869 +// in the documentation and/or other materials provided with the
  1870 +// distribution.
  1871 +//     * Neither the name of Google Inc. nor the names of its
  1872 +// contributors may be used to endorse or promote products derived from
  1873 +// this software without specific prior written permission.
  1874 +//
  1875 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  1876 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  1877 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  1878 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  1879 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  1880 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  1881 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  1882 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  1883 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1884 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  1885 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1887 +#include <string>
  1888 +#include <map>
  1890 +#include <stdlib.h>
  1891 +#include <string.h>
  1893 +#include "common/unique_string.h"
  1895 +namespace google_breakpad {
  1897 +///////////////////////////////////////////////////////////////////
  1898 +// UniqueString
  1899 +//
  1900 +class UniqueString {
  1901 + public:
  1902 +  UniqueString(string str) { str_ = strdup(str.c_str()); }
  1903 +  ~UniqueString() { free(reinterpret_cast<void*>(const_cast<char*>(str_))); }
  1904 +  const char* str_;
  1905 +};
  1907 +class UniqueStringUniverse {
  1908 + public:
  1909 +  UniqueStringUniverse() {};
  1910 +  const UniqueString* FindOrCopy(string str) {
  1911 +    std::map<string, UniqueString*>::iterator it = map_.find(str);
  1912 +    if (it == map_.end()) {
  1913 +      UniqueString* ustr = new UniqueString(str);
  1914 +      map_[str] = ustr;
  1915 +      return ustr;
  1916 +    } else {
  1917 +      return it->second;
  1918 +    }
  1919 +  }
  1920 + private:
  1921 +  std::map<string, UniqueString*> map_;
  1922 +};
  1924 +//
  1925 +///////////////////////////////////////////////////////////////////
  1928 +static UniqueStringUniverse* sUSU = NULL;
  1931 +// This isn't threadsafe.
  1932 +const UniqueString* ToUniqueString(string str) {
  1933 +  if (!sUSU) {
  1934 +    sUSU = new UniqueStringUniverse();
  1935 +  }
  1936 +  return sUSU->FindOrCopy(str);
  1937 +}
  1939 +// This isn't threadsafe.
  1940 +const UniqueString* ToUniqueString_n(const char* str, size_t n) {
  1941 +  if (!sUSU) {
  1942 +    sUSU = new UniqueStringUniverse();
  1943 +  }
  1944 +  string key(str, n);
  1945 +  return sUSU->FindOrCopy(key);
  1946 +}
  1948 +const char Index(const UniqueString* us, int ix)
  1949 +{
  1950 +  return us->str_[ix];
  1951 +}
  1953 +const char* const FromUniqueString(const UniqueString* ustr)
  1954 +{
  1955 +  return ustr->str_;
  1956 +}
  1958 +int StrcmpUniqueString(const UniqueString* us1, const UniqueString* us2) {
  1959 +  return strcmp(us1->str_, us2->str_);
  1960 +}
  1962 +bool LessThan_UniqueString(const UniqueString* us1, const UniqueString* us2) {
  1963 +  int r = StrcmpUniqueString(us1, us2);
  1964 +  return r < 0;
  1965 +}
  1967 +}  // namespace google_breakpad
  1968 diff --git a/src/common/unique_string.h b/src/common/unique_string.h
  1969 new file mode 100644
  1970 --- /dev/null
  1971 +++ b/src/common/unique_string.h
  1972 @@ -0,0 +1,239 @@
  1973 +// Copyright (c) 2013 Google Inc.
  1974 +// All rights reserved.
  1975 +//
  1976 +// Redistribution and use in source and binary forms, with or without
  1977 +// modification, are permitted provided that the following conditions are
  1978 +// met:
  1979 +//
  1980 +//     * Redistributions of source code must retain the above copyright
  1981 +// notice, this list of conditions and the following disclaimer.
  1982 +//     * Redistributions in binary form must reproduce the above
  1983 +// copyright notice, this list of conditions and the following disclaimer
  1984 +// in the documentation and/or other materials provided with the
  1985 +// distribution.
  1986 +//     * Neither the name of Google Inc. nor the names of its
  1987 +// contributors may be used to endorse or promote products derived from
  1988 +// this software without specific prior written permission.
  1989 +//
  1990 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  1991 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  1992 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  1993 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  1994 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  1995 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  1996 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  1997 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  1998 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1999 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  2000 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  2002 +#ifndef COMMON_UNIQUE_STRING_H_
  2003 +#define COMMON_UNIQUE_STRING_H_
  2005 +#include <string>
  2006 +#include "common/using_std_string.h"
  2008 +namespace google_breakpad {
  2010 +// Abstract type
  2011 +class UniqueString;
  2013 +// Unique-ify a string.  |ToUniqueString| can never return NULL.
  2014 +const UniqueString* ToUniqueString(string);
  2016 +// ditto, starting instead from the first n characters of a C string
  2017 +const UniqueString* ToUniqueString_n(const char* str, size_t n);
  2019 +// Pull chars out of the string.  No range checking.
  2020 +const char Index(const UniqueString*, int);
  2022 +// Get the contained C string (debugging only)
  2023 +const char* const FromUniqueString(const UniqueString*);
  2025 +// Do a strcmp-style comparison on the contained C string
  2026 +int StrcmpUniqueString(const UniqueString*, const UniqueString*);
  2028 +// Less-than comparison of two UniqueStrings, usable for std::sort.
  2029 +bool LessThan_UniqueString(const UniqueString*, const UniqueString*);
  2031 +// Some handy pre-uniqified strings.  Z is an escape character:
  2032 +//   ZS        '$'
  2033 +//   ZD        '.'
  2034 +//   Zeq       '='
  2035 +//   Zplus     '+'
  2036 +//   Zstar     '*'
  2037 +//   Zslash    '/'
  2038 +//   Zpercent  '%'
  2039 +//   Zat       '@'
  2040 +//   Zcaret    '^'
  2042 +// Note that ustr__empty and (UniqueString*)NULL are considered
  2043 +// to be different.
  2044 +//
  2045 +// Unfortunately these have to be written as functions so as to
  2046 +// make them safe to use in static initialisers.
  2048 +// ""
  2049 +inline static const UniqueString* ustr__empty() {
  2050 +  static const UniqueString* us = NULL;
  2051 +  if (!us) us = ToUniqueString("");
  2052 +  return us;
  2053 +}
  2055 +// "$eip"
  2056 +inline static const UniqueString* ustr__ZSeip() {
  2057 +  static const UniqueString* us = NULL;
  2058 +  if (!us) us = ToUniqueString("$eip");
  2059 +  return us;
  2060 +}
  2062 +// "$ebp"
  2063 +inline static const UniqueString* ustr__ZSebp() {
  2064 +  static const UniqueString* us = NULL;
  2065 +  if (!us) us = ToUniqueString("$ebp");
  2066 +  return us;
  2067 +}
  2069 +// "$esp"
  2070 +inline static const UniqueString* ustr__ZSesp() {
  2071 +  static const UniqueString* us = NULL;
  2072 +  if (!us) us = ToUniqueString("$esp");
  2073 +  return us;
  2074 +}
  2076 +// "$ebx"
  2077 +inline static const UniqueString* ustr__ZSebx() {
  2078 +  static const UniqueString* us = NULL;
  2079 +  if (!us) us = ToUniqueString("$ebx");
  2080 +  return us;
  2081 +}
  2083 +// "$esi"
  2084 +inline static const UniqueString* ustr__ZSesi() {
  2085 +  static const UniqueString* us = NULL;
  2086 +  if (!us) us = ToUniqueString("$esi");
  2087 +  return us;
  2088 +}
  2090 +// "$edi"
  2091 +inline static const UniqueString* ustr__ZSedi() {
  2092 +  static const UniqueString* us = NULL;
  2093 +  if (!us) us = ToUniqueString("$edi");
  2094 +  return us;
  2095 +}
  2097 +// ".cbCalleeParams"
  2098 +inline static const UniqueString* ustr__ZDcbCalleeParams() {
  2099 +  static const UniqueString* us = NULL;
  2100 +  if (!us) us = ToUniqueString(".cbCalleeParams");
  2101 +  return us;
  2102 +}
  2104 +// ".cbSavedRegs"
  2105 +inline static const UniqueString* ustr__ZDcbSavedRegs() {
  2106 +  static const UniqueString* us = NULL;
  2107 +  if (!us) us = ToUniqueString(".cbSavedRegs");
  2108 +  return us;
  2109 +}
  2111 +// ".cbLocals"
  2112 +inline static const UniqueString* ustr__ZDcbLocals() {
  2113 +  static const UniqueString* us = NULL;
  2114 +  if (!us) us = ToUniqueString(".cbLocals");
  2115 +  return us;
  2116 +}
  2118 +// ".raSearchStart"
  2119 +inline static const UniqueString* ustr__ZDraSearchStart() {
  2120 +  static const UniqueString* us = NULL;
  2121 +  if (!us) us = ToUniqueString(".raSearchStart");
  2122 +  return us;
  2123 +}
  2125 +// ".raSearch"
  2126 +inline static const UniqueString* ustr__ZDraSearch() {
  2127 +  static const UniqueString* us = NULL;
  2128 +  if (!us) us = ToUniqueString(".raSearch");
  2129 +  return us;
  2130 +}
  2132 +// ".cbParams"
  2133 +inline static const UniqueString* ustr__ZDcbParams() {
  2134 +  static const UniqueString* us = NULL;
  2135 +  if (!us) us = ToUniqueString(".cbParams");
  2136 +  return us;
  2137 +}
  2139 +// "+"
  2140 +inline static const UniqueString* ustr__Zplus() {
  2141 +  static const UniqueString* us = NULL;
  2142 +  if (!us) us = ToUniqueString("+");
  2143 +  return us;
  2144 +}
  2146 +// "-"
  2147 +inline static const UniqueString* ustr__Zminus() {
  2148 +  static const UniqueString* us = NULL;
  2149 +  if (!us) us = ToUniqueString("-");
  2150 +  return us;
  2151 +}
  2153 +// "*"
  2154 +inline static const UniqueString* ustr__Zstar() {
  2155 +  static const UniqueString* us = NULL;
  2156 +  if (!us) us = ToUniqueString("*");
  2157 +  return us;
  2158 +}
  2160 +// "/"
  2161 +inline static const UniqueString* ustr__Zslash() {
  2162 +  static const UniqueString* us = NULL;
  2163 +  if (!us) us = ToUniqueString("/");
  2164 +  return us;
  2165 +}
  2167 +// "%"
  2168 +inline static const UniqueString* ustr__Zpercent() {
  2169 +  static const UniqueString* us = NULL;
  2170 +  if (!us) us = ToUniqueString("%");
  2171 +  return us;
  2172 +}
  2174 +// "@"
  2175 +inline static const UniqueString* ustr__Zat() {
  2176 +  static const UniqueString* us = NULL;
  2177 +  if (!us) us = ToUniqueString("@");
  2178 +  return us;
  2179 +}
  2181 +// "^"
  2182 +inline static const UniqueString* ustr__Zcaret() {
  2183 +  static const UniqueString* us = NULL;
  2184 +  if (!us) us = ToUniqueString("^");
  2185 +  return us;
  2186 +}
  2188 +// "="
  2189 +inline static const UniqueString* ustr__Zeq() {
  2190 +  static const UniqueString* us = NULL;
  2191 +  if (!us) us = ToUniqueString("=");
  2192 +  return us;
  2193 +}
  2195 +// ".cfa"
  2196 +inline static const UniqueString* ustr__ZDcfa() {
  2197 +  static const UniqueString* us = NULL;
  2198 +  if (!us) us = ToUniqueString(".cfa");
  2199 +  return us;
  2200 +}
  2202 +// ".ra"
  2203 +inline static const UniqueString* ustr__ZDra() {
  2204 +  static const UniqueString* us = NULL;
  2205 +  if (!us) us = ToUniqueString(".ra");
  2206 +  return us;
  2207 +}
  2209 +}  // namespace google_breakpad
  2211 +#endif  // COMMON_UNIQUE_STRING_H_
  2212 diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
  2213 --- a/src/processor/basic_source_line_resolver_unittest.cc
  2214 +++ b/src/processor/basic_source_line_resolver_unittest.cc
  2215 @@ -43,21 +43,30 @@
  2216  #include "processor/windows_frame_info.h"
  2217  #include "processor/cfi_frame_info.h"
  2219  namespace {
  2221  using google_breakpad::BasicSourceLineResolver;
  2222  using google_breakpad::CFIFrameInfo;
  2223  using google_breakpad::CodeModule;
  2224 +using google_breakpad::FromUniqueString;
  2225  using google_breakpad::MemoryRegion;
  2226  using google_breakpad::StackFrame;
  2227 +using google_breakpad::ToUniqueString;
  2228  using google_breakpad::WindowsFrameInfo;
  2229  using google_breakpad::linked_ptr;
  2230  using google_breakpad::scoped_ptr;
  2231 +using google_breakpad::ustr__ZDcfa;
  2232 +using google_breakpad::ustr__ZDra;
  2233 +using google_breakpad::ustr__ZSebx;
  2234 +using google_breakpad::ustr__ZSebp;
  2235 +using google_breakpad::ustr__ZSedi;
  2236 +using google_breakpad::ustr__ZSesi;
  2237 +using google_breakpad::ustr__ZSesp;
  2239  class TestCodeModule : public CodeModule {
  2240   public:
  2241    TestCodeModule(string code_file) : code_file_(code_file) {}
  2242    virtual ~TestCodeModule() {}
  2244    virtual uint64_t base_address() const { return 0; }
  2245    virtual uint64_t size() const { return 0xb000; }
  2246 @@ -107,34 +116,34 @@
  2247  // association. (That is, ACTUAL's associations should be a subset of
  2248  // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
  2249  // ".cfa".
  2250  static bool VerifyRegisters(
  2251      const char *file, int line,
  2252      const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
  2253      const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
  2254    CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
  2255 -  a = actual.find(".cfa");
  2256 +  a = actual.find(ustr__ZDcfa());
  2257    if (a == actual.end())
  2258      return false;
  2259 -  a = actual.find(".ra");
  2260 +  a = actual.find(ustr__ZDra());
  2261    if (a == actual.end())
  2262      return false;
  2263    for (a = actual.begin(); a != actual.end(); a++) {
  2264      CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
  2265        expected.find(a->first);
  2266      if (e == expected.end()) {
  2267        fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
  2268 -              file, line, a->first.c_str(), a->second);
  2269 +              file, line, FromUniqueString(a->first), a->second);
  2270        return false;
  2272      if (e->second != a->second) {
  2273        fprintf(stderr,
  2274                "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
  2275 -              file, line, a->first.c_str(), a->second, e->second);
  2276 +              file, line, FromUniqueString(a->first), a->second, e->second);
  2277        return false;
  2279      // Don't complain if this doesn't recover all registers. Although
  2280      // the DWARF spec says that unmentioned registers are undefined,
  2281      // GCC uses omission to mean that they are unchanged.
  2283    return true;
  2285 @@ -254,81 +263,81 @@
  2287    CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
  2288    CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
  2289    CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
  2290    MockMemoryRegion memory;
  2292    // Regardless of which instruction evaluation takes place at, it
  2293    // should produce the same values for the caller's registers.
  2294 -  expected_caller_registers[".cfa"] = 0x1001c;
  2295 -  expected_caller_registers[".ra"]  = 0xf6438648;
  2296 -  expected_caller_registers["$ebp"] = 0x10038;
  2297 -  expected_caller_registers["$ebx"] = 0x98ecadc3;
  2298 -  expected_caller_registers["$esi"] = 0x878f7524;
  2299 -  expected_caller_registers["$edi"] = 0x6312f9a5;
  2300 +  expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
  2301 +  expected_caller_registers[ustr__ZDra()]  = 0xf6438648;
  2302 +  expected_caller_registers[ustr__ZSebp()] = 0x10038;
  2303 +  expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
  2304 +  expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
  2305 +  expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
  2307    frame.instruction = 0x3d40;
  2308    frame.module = &module1;
  2309    current_registers.clear();
  2310 -  current_registers["$esp"] = 0x10018;
  2311 -  current_registers["$ebp"] = 0x10038;
  2312 -  current_registers["$ebx"] = 0x98ecadc3;
  2313 -  current_registers["$esi"] = 0x878f7524;
  2314 -  current_registers["$edi"] = 0x6312f9a5;
  2315 +  current_registers[ustr__ZSesp()] = 0x10018;
  2316 +  current_registers[ustr__ZSebp()] = 0x10038;
  2317 +  current_registers[ustr__ZSebx()] = 0x98ecadc3;
  2318 +  current_registers[ustr__ZSesi()] = 0x878f7524;
  2319 +  current_registers[ustr__ZSedi()] = 0x6312f9a5;
  2320    cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
  2321    ASSERT_TRUE(cfi_frame_info.get());
  2322    ASSERT_TRUE(cfi_frame_info.get()
  2323                ->FindCallerRegs<uint32_t>(current_registers, memory,
  2324                                            &caller_registers));
  2325    ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
  2326                                expected_caller_registers, caller_registers));
  2328    frame.instruction = 0x3d41;
  2329 -  current_registers["$esp"] = 0x10014;
  2330 +  current_registers[ustr__ZSesp()] = 0x10014;
  2331    cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
  2332    ASSERT_TRUE(cfi_frame_info.get());
  2333    ASSERT_TRUE(cfi_frame_info.get()
  2334                ->FindCallerRegs<uint32_t>(current_registers, memory,
  2335                                            &caller_registers));
  2336    ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
  2337                                expected_caller_registers, caller_registers));
  2339    frame.instruction = 0x3d43;
  2340 -  current_registers["$ebp"] = 0x10014;
  2341 +  current_registers[ustr__ZSebp()] = 0x10014;
  2342    cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
  2343    ASSERT_TRUE(cfi_frame_info.get());
  2344    ASSERT_TRUE(cfi_frame_info.get()
  2345                ->FindCallerRegs<uint32_t>(current_registers, memory,
  2346                                            &caller_registers));
  2347    VerifyRegisters(__FILE__, __LINE__,
  2348                    expected_caller_registers, caller_registers);
  2350    frame.instruction = 0x3d54;
  2351 -  current_registers["$ebx"] = 0x6864f054U;
  2352 +  current_registers[ustr__ZSebx()] = 0x6864f054U;
  2353    cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
  2354    ASSERT_TRUE(cfi_frame_info.get());
  2355    ASSERT_TRUE(cfi_frame_info.get()
  2356                ->FindCallerRegs<uint32_t>(current_registers, memory,
  2357                                            &caller_registers));
  2358    VerifyRegisters(__FILE__, __LINE__,
  2359                    expected_caller_registers, caller_registers);
  2361    frame.instruction = 0x3d5a;
  2362 -  current_registers["$esi"] = 0x6285f79aU;
  2363 +  current_registers[ustr__ZSesi()] = 0x6285f79aU;
  2364    cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
  2365    ASSERT_TRUE(cfi_frame_info.get());
  2366    ASSERT_TRUE(cfi_frame_info.get()
  2367                ->FindCallerRegs<uint32_t>(current_registers, memory,
  2368                                            &caller_registers));
  2369    VerifyRegisters(__FILE__, __LINE__,
  2370                    expected_caller_registers, caller_registers);
  2372    frame.instruction = 0x3d84;
  2373 -  current_registers["$edi"] = 0x64061449U;
  2374 +  current_registers[ustr__ZSedi()] = 0x64061449U;
  2375    cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
  2376    ASSERT_TRUE(cfi_frame_info.get());
  2377    ASSERT_TRUE(cfi_frame_info.get()
  2378                ->FindCallerRegs<uint32_t>(current_registers, memory,
  2379                                            &caller_registers));
  2380    VerifyRegisters(__FILE__, __LINE__,
  2381                    expected_caller_registers, caller_registers);
  2383 diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
  2384 --- a/src/processor/cfi_frame_info.cc
  2385 +++ b/src/processor/cfi_frame_info.cc
  2386 @@ -31,16 +31,17 @@
  2388  // cfi_frame_info.cc: Implementation of CFIFrameInfo class.
  2389  // See cfi_frame_info.h for details.
  2391  #include "processor/cfi_frame_info.h"
  2393  #include <string.h>
  2395 +#include <algorithm>
  2396  #include <sstream>
  2398  #include "common/scoped_ptr.h"
  2399  #include "processor/postfix_evaluator-inl.h"
  2401  namespace google_breakpad {
  2403  #ifdef _WIN32
  2404 @@ -65,33 +66,33 @@
  2405    V cfa;
  2406    working = registers;
  2407    if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
  2408      return false;
  2410    // Then, compute the return address.
  2411    V ra;
  2412    working = registers;
  2413 -  working[".cfa"] = cfa;
  2414 +  working[ustr__ZDcfa()] = cfa;
  2415    if (!evaluator.EvaluateForValue(ra_rule_, &ra))
  2416      return false;
  2418    // Now, compute values for all the registers register_rules_ mentions.
  2419    for (RuleMap::const_iterator it = register_rules_.begin();
  2420         it != register_rules_.end(); it++) {
  2421      V value;
  2422      working = registers;
  2423 -    working[".cfa"] = cfa;
  2424 +    working[ustr__ZDcfa()] = cfa;
  2425      if (!evaluator.EvaluateForValue(it->second, &value))
  2426        return false;
  2427      (*caller_registers)[it->first] = value;
  2430 -  (*caller_registers)[".ra"] = ra;
  2431 -  (*caller_registers)[".cfa"] = cfa;
  2432 +  (*caller_registers)[ustr__ZDra()] = ra;
  2433 +  (*caller_registers)[ustr__ZDcfa()] = cfa;
  2435    return true;
  2438  // Explicit instantiations for 32-bit and 64-bit architectures.
  2439  template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
  2440      const RegisterValueMap<uint32_t> &registers,
  2441      const MemoryRegion &memory,
  2442 @@ -107,81 +108,98 @@
  2443    if (!cfa_rule_.invalid()) {
  2444      stream << ".cfa: " << cfa_rule_;
  2446    if (!ra_rule_.invalid()) {
  2447      if (static_cast<std::streamoff>(stream.tellp()) != 0)
  2448        stream << " ";
  2449      stream << ".ra: " << ra_rule_;
  2452 +  // Visit the register rules in alphabetical order.  Because
  2453 +  // register_rules_ has the elements in some arbitrary order,
  2454 +  // get the names out into a vector, sort them, and visit in
  2455 +  // sorted order.
  2456 +  std::vector<const UniqueString*> rr_names;
  2457    for (RuleMap::const_iterator iter = register_rules_.begin();
  2458         iter != register_rules_.end();
  2459         ++iter) {
  2460 +    rr_names.push_back(iter->first);
  2461 +  }
  2463 +  std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString);
  2465 +  // Now visit the register rules in alphabetical order.
  2466 +  for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin();
  2467 +       name != rr_names.end();
  2468 +       ++name) {
  2469 +    const UniqueString* nm = *name;
  2470 +    Module::Expr rule = register_rules_.find(nm)->second;
  2471      if (static_cast<std::streamoff>(stream.tellp()) != 0)
  2472        stream << " ";
  2473 -    stream << iter->first << ": " << iter->second;
  2474 +    stream << FromUniqueString(nm) << ": " << rule;
  2477    return stream.str();
  2480  bool CFIRuleParser::Parse(const string &rule_set) {
  2481    size_t rule_set_len = rule_set.size();
  2482    scoped_array<char> working_copy(new char[rule_set_len + 1]);
  2483    memcpy(working_copy.get(), rule_set.data(), rule_set_len);
  2484    working_copy[rule_set_len] = '\0';
  2486 -  name_.clear();
  2487 +  name_ = ustr__empty();
  2488    expression_.clear();
  2490    char *cursor;
  2491    static const char token_breaks[] = " \t\r\n";
  2492    char *token = strtok_r(working_copy.get(), token_breaks, &cursor);
  2494    for (;;) {
  2495      // End of rule set?
  2496      if (!token) return Report();
  2498      // Register/pseudoregister name?
  2499      size_t token_len = strlen(token);
  2500      if (token_len >= 1 && token[token_len - 1] == ':') {
  2501        // Names can't be empty.
  2502        if (token_len < 2) return false;
  2503        // If there is any pending content, report it.
  2504 -      if (!name_.empty() || !expression_.empty()) {
  2505 +      if (name_ != ustr__empty() || !expression_.empty()) {
  2506          if (!Report()) return false;
  2508 -      name_.assign(token, token_len - 1);
  2509 +      name_ = ToUniqueString_n(token, token_len - 1);
  2510        expression_.clear();
  2511      } else {
  2512        // Another expression component.
  2513        assert(token_len > 0); // strtok_r guarantees this, I think.
  2514        if (!expression_.empty())
  2515          expression_ += ' ';
  2516        expression_ += token;
  2518      token = strtok_r(NULL, token_breaks, &cursor);
  2522  bool CFIRuleParser::Report() {
  2523 -  if (name_.empty() || expression_.empty()) return false;
  2524 -  if (name_ == ".cfa") handler_->CFARule(expression_);
  2525 -  else if (name_ == ".ra") handler_->RARule(expression_);
  2526 +  if (name_ == ustr__empty() || expression_.empty()) return false;
  2527 +  if (name_ == ustr__ZDcfa()) handler_->CFARule(expression_);
  2528 +  else if (name_ == ustr__ZDra()) handler_->RARule(expression_);
  2529    else handler_->RegisterRule(name_, expression_);
  2530    return true;
  2533  void CFIFrameInfoParseHandler::CFARule(const string &expression) {
  2534    // 'expression' is a postfix expression string.
  2535    frame_info_->SetCFARule(Module::Expr(expression));
  2538  void CFIFrameInfoParseHandler::RARule(const string &expression) {
  2539    frame_info_->SetRARule(Module::Expr(expression));
  2542 -void CFIFrameInfoParseHandler::RegisterRule(const string &name,
  2543 +void CFIFrameInfoParseHandler::RegisterRule(const UniqueString* name,
  2544                                              const string &expression) {
  2545    frame_info_->SetRegisterRule(name, Module::Expr(expression));
  2548  } // namespace google_breakpad
  2549 diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
  2550 --- a/src/processor/cfi_frame_info.h
  2551 +++ b/src/processor/cfi_frame_info.h
  2552 @@ -37,16 +37,17 @@
  2554  #ifndef PROCESSOR_CFI_FRAME_INFO_H_
  2555  #define PROCESSOR_CFI_FRAME_INFO_H_
  2557  #include <map>
  2558  #include <string>
  2560  #include "common/using_std_string.h"
  2561 +#include "common/unique_string.h"
  2562  #include "google_breakpad/common/breakpad_types.h"
  2563  #include "common/module.h"
  2565  namespace google_breakpad {
  2567  using std::map;
  2569  class MemoryRegion;
  2570 @@ -63,24 +64,24 @@
  2571  // changes given by the 'STACK CFI' records up to our instruction's
  2572  // address. Then, use the FindCallerRegs member function to apply the
  2573  // rules to the callee frame's register values, yielding the caller
  2574  // frame's register values.
  2575  class CFIFrameInfo {
  2576   public:
  2577    // A map from register names onto values.
  2578    template<typename ValueType> class RegisterValueMap:
  2579 -    public map<string, ValueType> { };
  2580 +    public map<const UniqueString*, ValueType> { };
  2582    // Set the expression for computing a call frame address, return
  2583    // address, or register's value. At least the CFA rule and the RA
  2584    // rule must be set before calling FindCallerRegs.
  2585    void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; }
  2586    void SetRARule(const Module::Expr& rule)  { ra_rule_ = rule; }
  2587 -  void SetRegisterRule(const string& register_name,
  2588 +  void SetRegisterRule(const UniqueString* register_name,
  2589                         const Module::Expr& rule) {
  2590      register_rules_[register_name] = rule;
  2593    // Compute the values of the calling frame's registers, according to
  2594    // this rule set. Use ValueType in expression evaluation; this
  2595    // should be uint32_t on machines with 32-bit addresses, or
  2596    // uint64_t on machines with 64-bit addresses.
  2597 @@ -104,17 +105,17 @@
  2599    // Serialize the rules in this object into a string in the format
  2600    // of STACK CFI records.
  2601    string Serialize() const;
  2603   private:
  2605    // A map from register names onto evaluation rules.
  2606 -  typedef map<string, Module::Expr> RuleMap;
  2607 +  typedef map<const UniqueString*, Module::Expr> RuleMap;
  2609    // An expression for computing the current frame's CFA (call
  2610    // frame address). The CFA is a reference address for the frame that
  2611    // remains unchanged throughout the frame's lifetime. You should
  2612    // evaluate this expression with a dictionary initially populated
  2613    // with the values of the current frame's known registers.
  2614    Module::Expr cfa_rule_;
  2616 @@ -145,17 +146,18 @@
  2617      Handler() { }
  2618      virtual ~Handler() { }
  2620      // The input specifies EXPRESSION as the CFA/RA computation rule.
  2621      virtual void CFARule(const string &expression) = 0;
  2622      virtual void RARule(const string &expression) = 0;
  2624      // The input specifies EXPRESSION as the recovery rule for register NAME.
  2625 -    virtual void RegisterRule(const string &name, const string &expression) = 0;
  2626 +    virtual void RegisterRule(const UniqueString* name,
  2627 +                              const string &expression) = 0;
  2628    };
  2630    // Construct a parser which feeds its results to HANDLER.
  2631    CFIRuleParser(Handler *handler) : handler_(handler) { }
  2633    // Parse RULE_SET as a set of CFA computation and RA/register
  2634    // recovery rules, as appearing in STACK CFI records. Report the
  2635    // results of parsing by making the appropriate calls to handler_.
  2636 @@ -165,30 +167,31 @@
  2637   private:
  2638    // Report any accumulated rule to handler_
  2639    bool Report();
  2641    // The handler to which the parser reports its findings.
  2642    Handler *handler_;
  2644    // Working data.
  2645 -  string name_, expression_;
  2646 +  const UniqueString* name_;
  2647 +  string expression_;
  2648  };
  2650  // A handler for rule set parsing that populates a CFIFrameInfo with
  2651  // the results.
  2652  class CFIFrameInfoParseHandler: public CFIRuleParser::Handler {
  2653   public:
  2654    // Populate FRAME_INFO with the results of parsing.
  2655    CFIFrameInfoParseHandler(CFIFrameInfo *frame_info)
  2656        : frame_info_(frame_info) { }
  2658    void CFARule(const string &expression);
  2659    void RARule(const string &expression);
  2660 -  void RegisterRule(const string &name, const string &expression);
  2661 +  void RegisterRule(const UniqueString* name, const string &expression);
  2663   private:
  2664    CFIFrameInfo *frame_info_;
  2665  };
  2667  // A utility class template for simple 'STACK CFI'-driven stack walkers.
  2668  // Given a CFIFrameInfo instance, a table describing the architecture's
  2669  // register set, and a context holding the last frame's registers, an
  2670 @@ -205,24 +208,24 @@
  2671  // uint32_t or uint64_t. RawContextType should be the raw context
  2672  // structure type for this architecture.
  2673  template <typename RegisterType, class RawContextType>
  2674  class SimpleCFIWalker {
  2675   public:
  2676    // A structure describing one architecture register.
  2677    struct RegisterSet {
  2678      // The register name, as it appears in STACK CFI rules.
  2679 -    const char *name;
  2680 +    const UniqueString* name;
  2682      // An alternate name that the register's value might be found
  2683      // under in a register value dictionary, or NULL. When generating
  2684      // names, prefer NAME to this value. It's common to list ".cfa" as
  2685      // an alternative name for the stack pointer, and ".ra" as an
  2686      // alternative name for the instruction pointer.
  2687 -    const char *alternate_name;
  2688 +    const UniqueString* alternate_name;
  2690      // True if the callee is expected to preserve the value of this
  2691      // register. If this flag is true for some register R, and the STACK
  2692      // CFI records provide no rule to recover R, then SimpleCFIWalker
  2693      // assumes that the callee has not changed R's value, and the caller's
  2694      // value for R is that currently in the callee's context.
  2695      bool callee_saves;
  2697 diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
  2698 --- a/src/processor/cfi_frame_info_unittest.cc
  2699 +++ b/src/processor/cfi_frame_info_unittest.cc
  2700 @@ -38,19 +38,24 @@
  2701  #include "common/module.h"
  2702  #include "common/using_std_string.h"
  2703  #include "processor/cfi_frame_info.h"
  2704  #include "google_breakpad/processor/memory_region.h"
  2706  using google_breakpad::CFIFrameInfo;
  2707  using google_breakpad::CFIFrameInfoParseHandler;
  2708  using google_breakpad::CFIRuleParser;
  2709 +using google_breakpad::FromUniqueString;
  2710  using google_breakpad::MemoryRegion;
  2711  using google_breakpad::Module;
  2712  using google_breakpad::SimpleCFIWalker;
  2713 +using google_breakpad::ToUniqueString;
  2714 +using google_breakpad::UniqueString;
  2715 +using google_breakpad::ustr__ZDcfa;
  2716 +using google_breakpad::ustr__ZDra;
  2717  using testing::_;
  2718  using testing::A;
  2719  using testing::AtMost;
  2720  using testing::DoAll;
  2721  using testing::Return;
  2722  using testing::SetArgumentPointee;
  2723  using testing::Test;
  2725 @@ -107,41 +112,47 @@
  2726  TEST_F(Simple, SetCFAAndRARule) {
  2727    ExpectNoMemoryReferences();
  2729    cfi.SetCFARule(Module::Expr("330903416631436410"));
  2730    cfi.SetRARule(Module::Expr("5870666104170902211"));
  2731    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2732                                              &caller_registers));
  2733    ASSERT_EQ(2U, caller_registers.size());
  2734 -  ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]);
  2735 -  ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
  2736 +  ASSERT_EQ(330903416631436410ULL, caller_registers[ustr__ZDcfa()]);
  2737 +  ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
  2739    ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
  2740              cfi.Serialize());
  2743  TEST_F(Simple, SetManyRules) {
  2744    ExpectNoMemoryReferences();
  2746    cfi.SetCFARule(Module::Expr("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -"));
  2747    cfi.SetRARule(Module::Expr(".cfa 99804755 +"));
  2748 -  cfi.SetRegisterRule("register1", Module::Expr(".cfa 54370437 *"));
  2749 -  cfi.SetRegisterRule("vodkathumbscrewingly", Module::Expr("24076308 .cfa +"));
  2750 -  cfi.SetRegisterRule("pubvexingfjordschmaltzy", Module::Expr(".cfa 29801007 -"));
  2751 -  cfi.SetRegisterRule("uncopyrightables", Module::Expr("92642917 .cfa /"));
  2753 +  const UniqueString* reg1 = ToUniqueString("register1");
  2754 +  const UniqueString* reg2 = ToUniqueString("vodkathumbscrewingly");
  2755 +  const UniqueString* reg3 = ToUniqueString("pubvexingfjordschmaltzy");
  2756 +  const UniqueString* reg4 = ToUniqueString("uncopyrightables");
  2758 +  cfi.SetRegisterRule(reg1, Module::Expr(".cfa 54370437 *"));
  2759 +  cfi.SetRegisterRule(reg2, Module::Expr("24076308 .cfa +"));
  2760 +  cfi.SetRegisterRule(reg3, Module::Expr(".cfa 29801007 -"));
  2761 +  cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /"));
  2762    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2763                                              &caller_registers));
  2764    ASSERT_EQ(6U, caller_registers.size());
  2765 -  ASSERT_EQ(7664691U,           caller_registers[".cfa"]);
  2766 -  ASSERT_EQ(107469446U,         caller_registers[".ra"]);
  2767 -  ASSERT_EQ(416732599139967ULL, caller_registers["register1"]);
  2768 -  ASSERT_EQ(31740999U,          caller_registers["vodkathumbscrewingly"]);
  2769 -  ASSERT_EQ(-22136316ULL,       caller_registers["pubvexingfjordschmaltzy"]);
  2770 -  ASSERT_EQ(12U,                caller_registers["uncopyrightables"]);
  2771 +  ASSERT_EQ(7664691U,           caller_registers[ustr__ZDcfa()]);
  2772 +  ASSERT_EQ(107469446U,         caller_registers[ustr__ZDra()]);
  2773 +  ASSERT_EQ(416732599139967ULL, caller_registers[reg1]);
  2774 +  ASSERT_EQ(31740999U,          caller_registers[reg2]);
  2775 +  ASSERT_EQ(-22136316ULL,       caller_registers[reg3]);
  2776 +  ASSERT_EQ(12U,                caller_registers[reg4]);
  2777    ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
  2778              ".ra: .cfa 99804755 + "
  2779              "pubvexingfjordschmaltzy: .cfa 29801007 - "
  2780              "register1: .cfa 54370437 * "
  2781              "uncopyrightables: 92642917 .cfa / "
  2782              "vodkathumbscrewingly: 24076308 .cfa +",
  2783              cfi.Serialize());
  2785 @@ -150,18 +161,18 @@
  2786    ExpectNoMemoryReferences();
  2788    cfi.SetCFARule(Module::Expr("330903416631436410"));
  2789    cfi.SetRARule(Module::Expr("5870666104170902211"));
  2790    cfi.SetCFARule(Module::Expr("2828089117179001"));
  2791    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2792                                              &caller_registers));
  2793    ASSERT_EQ(2U, caller_registers.size());
  2794 -  ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]);
  2795 -  ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
  2796 +  ASSERT_EQ(2828089117179001ULL, caller_registers[ustr__ZDcfa()]);
  2797 +  ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
  2798    ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
  2799              cfi.Serialize());
  2802  class Scope: public CFIFixture, public Test { };
  2804  // There should be no value for .cfa in scope when evaluating the CFA rule.
  2805  TEST_F(Scope, CFALacksCFA) {
  2806 @@ -183,37 +194,39 @@
  2807                                               &caller_registers));
  2810  // The current frame's registers should be in scope when evaluating
  2811  // the CFA rule.
  2812  TEST_F(Scope, CFASeesCurrentRegs) {
  2813    ExpectNoMemoryReferences();
  2815 -  registers[".baraminology"] = 0x06a7bc63e4f13893ULL;
  2816 -  registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL;
  2817 +  const UniqueString* reg1 = ToUniqueString(".baraminology");
  2818 +  const UniqueString* reg2 = ToUniqueString(".ornithorhynchus");
  2819 +  registers[reg1] = 0x06a7bc63e4f13893ULL;
  2820 +  registers[reg2] = 0x5e0bf850bafce9d2ULL;
  2821    cfi.SetCFARule(Module::Expr(".baraminology .ornithorhynchus +"));
  2822    cfi.SetRARule(Module::Expr("0"));
  2823    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2824                                              &caller_registers));
  2825    ASSERT_EQ(2U, caller_registers.size());
  2826    ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
  2827 -            caller_registers[".cfa"]);
  2828 +            caller_registers[ustr__ZDcfa()]);
  2831  // .cfa should be in scope in the return address expression.
  2832  TEST_F(Scope, RASeesCFA) {
  2833    ExpectNoMemoryReferences();
  2835    cfi.SetCFARule(Module::Expr("48364076"));
  2836    cfi.SetRARule(Module::Expr(".cfa"));
  2837    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2838                                              &caller_registers));
  2839    ASSERT_EQ(2U, caller_registers.size());
  2840 -  ASSERT_EQ(48364076U, caller_registers[".ra"]);
  2841 +  ASSERT_EQ(48364076U, caller_registers[ustr__ZDra()]);
  2844  // There should be no value for .ra in scope when evaluating the CFA rule.
  2845  TEST_F(Scope, RALacksRA) {
  2846    ExpectNoMemoryReferences();
  2848    cfi.SetCFARule(Module::Expr("0"));
  2849    cfi.SetRARule(Module::Expr(".ra"));
  2850 @@ -221,64 +234,69 @@
  2851                                               &caller_registers));
  2854  // The current frame's registers should be in scope in the return
  2855  // address expression.
  2856  TEST_F(Scope, RASeesCurrentRegs) {
  2857    ExpectNoMemoryReferences();
  2859 -  registers["noachian"] = 0x54dc4a5d8e5eb503ULL;
  2860    cfi.SetCFARule(Module::Expr("10359370"));
  2861 -  cfi.SetRARule(Module::Expr("noachian"));
  2862 +  const UniqueString* reg1 = ToUniqueString("noachian");
  2863 +  registers[reg1] = 0x54dc4a5d8e5eb503ULL;
  2864 +  cfi.SetRARule(Module::Expr(reg1, 0, false));
  2865    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2866                                              &caller_registers));
  2867    ASSERT_EQ(2U, caller_registers.size());
  2868 -  ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]);
  2869 +  ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[ustr__ZDra()]);
  2872  // .cfa should be in scope for register rules.
  2873  TEST_F(Scope, RegistersSeeCFA) {
  2874    ExpectNoMemoryReferences();
  2876    cfi.SetCFARule(Module::Expr("6515179"));
  2877    cfi.SetRARule(Module::Expr(".cfa"));
  2878 -  cfi.SetRegisterRule("rogerian", Module::Expr(".cfa"));
  2879 +  const UniqueString* reg1 = ToUniqueString("rogerian");
  2880 +  cfi.SetRegisterRule(reg1, Module::Expr(".cfa"));
  2881    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2882                                              &caller_registers));
  2883    ASSERT_EQ(3U, caller_registers.size());
  2884 -  ASSERT_EQ(6515179U, caller_registers["rogerian"]);
  2885 +  ASSERT_EQ(6515179U, caller_registers[reg1]);
  2888  // The return address should not be in scope for register rules.
  2889  TEST_F(Scope, RegsLackRA) {
  2890    ExpectNoMemoryReferences();
  2892    cfi.SetCFARule(Module::Expr("42740329"));
  2893    cfi.SetRARule(Module::Expr("27045204"));
  2894 -  cfi.SetRegisterRule("$r1", Module::Expr(".ra"));
  2895 +  const UniqueString* reg1 = ToUniqueString("$r1");
  2896 +  cfi.SetRegisterRule(reg1, Module::Expr(".ra"));
  2897    ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2898                                               &caller_registers));
  2901  // Register rules can see the current frame's register values.
  2902  TEST_F(Scope, RegsSeeRegs) {
  2903    ExpectNoMemoryReferences();
  2905 -  registers["$r1"] = 0x6ed3582c4bedb9adULL;
  2906 -  registers["$r2"] = 0xd27d9e742b8df6d0ULL;
  2907 +  const UniqueString* reg1 = ToUniqueString("$r1");
  2908 +  const UniqueString* reg2 = ToUniqueString("$r2");
  2909 +  registers[reg1] = 0x6ed3582c4bedb9adULL;
  2910 +  registers[reg2] = 0xd27d9e742b8df6d0ULL;
  2911    cfi.SetCFARule(Module::Expr("88239303"));
  2912    cfi.SetRARule(Module::Expr("30503835"));
  2913 -  cfi.SetRegisterRule("$r1", Module::Expr("$r1 42175211 = $r2"));
  2914 -  cfi.SetRegisterRule("$r2", Module::Expr("$r2 21357221 = $r1"));
  2915 +  cfi.SetRegisterRule(reg1, Module::Expr("$r1 42175211 = $r2"));
  2916 +  cfi.SetRegisterRule(reg2, Module::Expr("$r2 21357221 = $r1"));
  2917    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2918                                              &caller_registers));
  2919    ASSERT_EQ(4U, caller_registers.size());
  2920 -  ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]);
  2921 -  ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]);
  2922 +  ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers[reg1]);
  2923 +  ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers[reg2]);
  2926  // Each rule's temporaries are separate.
  2927  TEST_F(Scope, SeparateTempsRA) {
  2928    ExpectNoMemoryReferences();
  2930    cfi.SetCFARule(Module::Expr("$temp1 76569129 = $temp1"));
  2931    cfi.SetRARule(Module::Expr("0"));
  2932 @@ -290,17 +308,17 @@
  2933    ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  2934                                               &caller_registers));
  2937  class MockCFIRuleParserHandler: public CFIRuleParser::Handler {
  2938   public:
  2939    MOCK_METHOD1(CFARule, void(const string &));
  2940    MOCK_METHOD1(RARule,  void(const string &));
  2941 -  MOCK_METHOD2(RegisterRule, void(const string &, const string &));
  2942 +  MOCK_METHOD2(RegisterRule, void(const UniqueString*, const string &));
  2943  };
  2945  // A fixture class for testing CFIRuleParser.
  2946  class CFIParserFixture {
  2947   public:
  2948    CFIParserFixture() : parser(&mock_handler) {
  2949      // Expect no parsing results to be reported to mock_handler. Individual
  2950      // tests can override this.
  2951 @@ -361,100 +379,100 @@
  2954  TEST_F(Parser, RA) {
  2955    EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return());
  2956    EXPECT_TRUE(parser.Parse(".ra: notoriety"));
  2959  TEST_F(Parser, Reg) {
  2960 -  EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous"))
  2961 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("nemo"), "mellifluous"))
  2962        .WillOnce(Return());
  2963    EXPECT_TRUE(parser.Parse("nemo: mellifluous"));
  2966  TEST_F(Parser, CFARARegs) {
  2967    EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return());
  2968    EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return());
  2969 -  EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian"))
  2970 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("galba"), "praetorian"))
  2971        .WillOnce(Return());
  2972 -  EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius"))
  2973 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("otho"), "vitellius"))
  2974        .WillOnce(Return());
  2975    EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression "
  2976                      "galba: praetorian otho: vitellius"));
  2979  TEST_F(Parser, Whitespace) {
  2980 -  EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression"))
  2981 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "r1 expression"))
  2982        .WillOnce(Return());
  2983 -  EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression"))
  2984 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r2"), "r2 expression"))
  2985        .WillOnce(Return());
  2986    EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n "
  2987                             "expression  \n"));
  2990  TEST_F(Parser, WhitespaceLoneColon) {
  2991    EXPECT_FALSE(parser.Parse("  \n:\t  "));
  2994  TEST_F(Parser, EmptyName) {
  2995 -  EXPECT_CALL(mock_handler, RegisterRule("reg", _))
  2996 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("reg"), _))
  2997        .Times(AtMost(1))
  2998        .WillRepeatedly(Return());
  2999    EXPECT_FALSE(parser.Parse("reg: expr1 : expr2"));
  3002  TEST_F(Parser, RuleLoneColon) {
  3003 -  EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
  3004 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "expr"))
  3005        .Times(AtMost(1))
  3006        .WillRepeatedly(Return());
  3007    EXPECT_FALSE(parser.Parse(" r1:   expr   :"));
  3010  TEST_F(Parser, RegNoExprRule) {
  3011 -  EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
  3012 +  EXPECT_CALL(mock_handler, RegisterRule(ToUniqueString("r1"), "expr"))
  3013        .Times(AtMost(1))
  3014        .WillRepeatedly(Return());
  3015    EXPECT_FALSE(parser.Parse("r0: r1:   expr"));
  3018  class ParseHandlerFixture: public CFIFixture {
  3019   public:
  3020    ParseHandlerFixture() : CFIFixture(), handler(&cfi) { }
  3021    CFIFrameInfoParseHandler handler;
  3022  };
  3024  class ParseHandler: public ParseHandlerFixture, public Test { };
  3026  TEST_F(ParseHandler, CFARARule) {
  3027    handler.CFARule("reg-for-cfa");
  3028    handler.RARule("reg-for-ra");
  3029 -  registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
  3030 -  registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
  3031 +  registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
  3032 +  registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
  3033    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  3034                                              &caller_registers));
  3035 -  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
  3036 -  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
  3037 +  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
  3038 +  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
  3041  TEST_F(ParseHandler, RegisterRules) {
  3042    handler.CFARule("reg-for-cfa");
  3043    handler.RARule("reg-for-ra");
  3044 -  handler.RegisterRule("reg1", "reg-for-reg1");
  3045 -  handler.RegisterRule("reg2", "reg-for-reg2");
  3046 -  registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
  3047 -  registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
  3048 -  registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL;
  3049 -  registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL;
  3050 +  handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1");
  3051 +  handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2");
  3052 +  registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
  3053 +  registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
  3054 +  registers[ToUniqueString("reg-for-reg1")] = 0x06cde8e2ff062481ULL;
  3055 +  registers[ToUniqueString("reg-for-reg2")] = 0xff0c4f76403173e2ULL;
  3056    ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
  3057                                              &caller_registers));
  3058 -  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
  3059 -  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
  3060 -  ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]);
  3061 -  ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]);
  3062 +  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
  3063 +  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
  3064 +  ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers[ToUniqueString("reg1")]);
  3065 +  ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers[ToUniqueString("reg2")]);
  3068  struct SimpleCFIWalkerFixture {
  3069    struct RawContext {
  3070      uint64_t r0, r1, r2, r3, r4, sp, pc;
  3071    };
  3072    enum Validity {
  3073      R0_VALID = 0x01,
  3074 @@ -475,23 +493,23 @@
  3075    CFIFrameInfo call_frame_info;
  3076    CFIWalker walker;
  3077    MockMemoryRegion memory;
  3078    RawContext callee_context, caller_context;
  3079  };
  3081  SimpleCFIWalkerFixture::CFIWalker::RegisterSet
  3082  SimpleCFIWalkerFixture::register_map[7] = {
  3083 -  { "r0", NULL,   true,  R0_VALID, &RawContext::r0 },
  3084 -  { "r1", NULL,   true,  R1_VALID, &RawContext::r1 },
  3085 -  { "r2", NULL,   false, R2_VALID, &RawContext::r2 },
  3086 -  { "r3", NULL,   false, R3_VALID, &RawContext::r3 },
  3087 -  { "r4", NULL,   true,  R4_VALID, &RawContext::r4 },
  3088 -  { "sp", ".cfa", true,  SP_VALID, &RawContext::sp },
  3089 -  { "pc", ".ra",  true,  PC_VALID, &RawContext::pc },
  3090 +  { ToUniqueString("r0"), NULL,   true,  R0_VALID, &RawContext::r0 },
  3091 +  { ToUniqueString("r1"), NULL,   true,  R1_VALID, &RawContext::r1 },
  3092 +  { ToUniqueString("r2"), NULL,   false, R2_VALID, &RawContext::r2 },
  3093 +  { ToUniqueString("r3"), NULL,   false, R3_VALID, &RawContext::r3 },
  3094 +  { ToUniqueString("r4"), NULL,   true,  R4_VALID, &RawContext::r4 },
  3095 +  { ToUniqueString("sp"), ustr__ZDcfa(), true,  SP_VALID, &RawContext::sp },
  3096 +  { ToUniqueString("pc"), ustr__ZDra(),  true,  PC_VALID, &RawContext::pc },
  3097  };
  3099  class SimpleWalker: public SimpleCFIWalkerFixture, public Test { };
  3101  TEST_F(SimpleWalker, Walk) {
  3102    // Stack_top is the current stack pointer, pointing to the lowest
  3103    // address of a frame that looks like this (all 64-bit words):
  3104    //
  3105 @@ -516,18 +534,20 @@
  3106    // Saved return address.
  3107    EXPECT_CALL(memory,
  3108                GetMemoryAtAddress(stack_top + 16, A<uint64_t *>()))
  3109        .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL),
  3110                              Return(true)));
  3112    call_frame_info.SetCFARule(Module::Expr("sp 24 +"));
  3113    call_frame_info.SetRARule(Module::Expr(".cfa 8 - ^"));
  3114 -  call_frame_info.SetRegisterRule("r0", Module::Expr(".cfa 24 - ^"));
  3115 -  call_frame_info.SetRegisterRule("r1", Module::Expr("r2"));
  3116 +  call_frame_info.SetRegisterRule(ToUniqueString("r0"),
  3117 +                                  Module::Expr(".cfa 24 - ^"));
  3118 +  call_frame_info.SetRegisterRule(ToUniqueString("r1"),
  3119 +                                  Module::Expr("r2"));
  3121    callee_context.r0 = 0x94e030ca79edd119ULL;
  3122    callee_context.r1 = 0x937b4d7e95ce52d9ULL;
  3123    callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1
  3124    // callee_context.r3 is not valid in callee.
  3125    // callee_context.r4 is not valid in callee.
  3126    callee_context.sp = stack_top;
  3127    callee_context.pc = 0x25b21b224311d280ULL;
  3128 diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
  3129 --- a/src/processor/fast_source_line_resolver_unittest.cc
  3130 +++ b/src/processor/fast_source_line_resolver_unittest.cc
  3131 @@ -51,25 +51,34 @@
  3132  #include "processor/module_serializer.h"
  3133  #include "processor/module_comparer.h"
  3135  namespace {
  3137  using google_breakpad::SourceLineResolverBase;
  3138  using google_breakpad::BasicSourceLineResolver;
  3139  using google_breakpad::FastSourceLineResolver;
  3140 +using google_breakpad::FromUniqueString;
  3141  using google_breakpad::ModuleSerializer;
  3142  using google_breakpad::ModuleComparer;
  3143  using google_breakpad::CFIFrameInfo;
  3144  using google_breakpad::CodeModule;
  3145  using google_breakpad::MemoryRegion;
  3146  using google_breakpad::StackFrame;
  3147 +using google_breakpad::ToUniqueString;
  3148  using google_breakpad::WindowsFrameInfo;
  3149  using google_breakpad::linked_ptr;
  3150  using google_breakpad::scoped_ptr;
  3151 +using google_breakpad::ustr__ZDcfa;
  3152 +using google_breakpad::ustr__ZDra;
  3153 +using google_breakpad::ustr__ZSebx;
  3154 +using google_breakpad::ustr__ZSebp;
  3155 +using google_breakpad::ustr__ZSedi;
  3156 +using google_breakpad::ustr__ZSesi;
  3157 +using google_breakpad::ustr__ZSesp;
  3159  class TestCodeModule : public CodeModule {
  3160   public:
  3161    explicit TestCodeModule(string code_file) : code_file_(code_file) {}
  3162    virtual ~TestCodeModule() {}
  3164    virtual uint64_t base_address() const { return 0; }
  3165    virtual uint64_t size() const { return 0xb000; }
  3166 @@ -119,34 +128,34 @@
  3167  // association. (That is, ACTUAL's associations should be a subset of
  3168  // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
  3169  // ".cfa".
  3170  static bool VerifyRegisters(
  3171      const char *file, int line,
  3172      const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
  3173      const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
  3174    CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
  3175 -  a = actual.find(".cfa");
  3176 +  a = actual.find(ustr__ZDcfa());
  3177    if (a == actual.end())
  3178      return false;
  3179 -  a = actual.find(".ra");
  3180 +  a = actual.find(ustr__ZDra());
  3181    if (a == actual.end())
  3182      return false;
  3183    for (a = actual.begin(); a != actual.end(); a++) {
  3184      CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
  3185        expected.find(a->first);
  3186      if (e == expected.end()) {
  3187        fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
  3188 -              file, line, a->first.c_str(), a->second);
  3189 +              file, line, FromUniqueString(a->first), a->second);
  3190        return false;
  3192      if (e->second != a->second) {
  3193        fprintf(stderr,
  3194                "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
  3195 -              file, line, a->first.c_str(), a->second, e->second);
  3196 +              file, line, FromUniqueString(a->first), a->second, e->second);
  3197        return false;
  3199      // Don't complain if this doesn't recover all registers. Although
  3200      // the DWARF spec says that unmentioned registers are undefined,
  3201      // GCC uses omission to mean that they are unchanged.
  3203    return true;
  3205 @@ -282,81 +291,81 @@
  3207    CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
  3208    CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
  3209    CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
  3210    MockMemoryRegion memory;
  3212    // Regardless of which instruction evaluation takes place at, it
  3213    // should produce the same values for the caller's registers.
  3214 -  expected_caller_registers[".cfa"] = 0x1001c;
  3215 -  expected_caller_registers[".ra"]  = 0xf6438648;
  3216 -  expected_caller_registers["$ebp"] = 0x10038;
  3217 -  expected_caller_registers["$ebx"] = 0x98ecadc3;
  3218 -  expected_caller_registers["$esi"] = 0x878f7524;
  3219 -  expected_caller_registers["$edi"] = 0x6312f9a5;
  3220 +  expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
  3221 +  expected_caller_registers[ustr__ZDra()]  = 0xf6438648;
  3222 +  expected_caller_registers[ustr__ZSebp()] = 0x10038;
  3223 +  expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
  3224 +  expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
  3225 +  expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
  3227    frame.instruction = 0x3d40;
  3228    frame.module = &module1;
  3229    current_registers.clear();
  3230 -  current_registers["$esp"] = 0x10018;
  3231 -  current_registers["$ebp"] = 0x10038;
  3232 -  current_registers["$ebx"] = 0x98ecadc3;
  3233 -  current_registers["$esi"] = 0x878f7524;
  3234 -  current_registers["$edi"] = 0x6312f9a5;
  3235 +  current_registers[ustr__ZSesp()] = 0x10018;
  3236 +  current_registers[ustr__ZSebp()] = 0x10038;
  3237 +  current_registers[ustr__ZSebx()] = 0x98ecadc3;
  3238 +  current_registers[ustr__ZSesi()] = 0x878f7524;
  3239 +  current_registers[ustr__ZSedi()] = 0x6312f9a5;
  3240    cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
  3241    ASSERT_TRUE(cfi_frame_info.get());
  3242    ASSERT_TRUE(cfi_frame_info.get()
  3243                ->FindCallerRegs<uint32_t>(current_registers, memory,
  3244                                            &caller_registers));
  3245    ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
  3246                                expected_caller_registers, caller_registers));
  3248    frame.instruction = 0x3d41;
  3249 -  current_registers["$esp"] = 0x10014;
  3250 +  current_registers[ustr__ZSesp()] = 0x10014;
  3251    cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
  3252    ASSERT_TRUE(cfi_frame_info.get());
  3253    ASSERT_TRUE(cfi_frame_info.get()
  3254                ->FindCallerRegs<uint32_t>(current_registers, memory,
  3255                                            &caller_registers));
  3256    ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
  3257                                expected_caller_registers, caller_registers));
  3259    frame.instruction = 0x3d43;
  3260 -  current_registers["$ebp"] = 0x10014;
  3261 +  current_registers[ustr__ZSebp()] = 0x10014;
  3262    cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
  3263    ASSERT_TRUE(cfi_frame_info.get());
  3264    ASSERT_TRUE(cfi_frame_info.get()
  3265                ->FindCallerRegs<uint32_t>(current_registers, memory,
  3266                                            &caller_registers));
  3267    VerifyRegisters(__FILE__, __LINE__,
  3268                    expected_caller_registers, caller_registers);
  3270    frame.instruction = 0x3d54;
  3271 -  current_registers["$ebx"] = 0x6864f054U;
  3272 +  current_registers[ustr__ZSebx()] = 0x6864f054U;
  3273    cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
  3274    ASSERT_TRUE(cfi_frame_info.get());
  3275    ASSERT_TRUE(cfi_frame_info.get()
  3276                ->FindCallerRegs<uint32_t>(current_registers, memory,
  3277                                            &caller_registers));
  3278    VerifyRegisters(__FILE__, __LINE__,
  3279                    expected_caller_registers, caller_registers);
  3281    frame.instruction = 0x3d5a;
  3282 -  current_registers["$esi"] = 0x6285f79aU;
  3283 +  current_registers[ustr__ZSesi()] = 0x6285f79aU;
  3284    cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
  3285    ASSERT_TRUE(cfi_frame_info.get());
  3286    ASSERT_TRUE(cfi_frame_info.get()
  3287                ->FindCallerRegs<uint32_t>(current_registers, memory,
  3288                                            &caller_registers));
  3289    VerifyRegisters(__FILE__, __LINE__,
  3290                    expected_caller_registers, caller_registers);
  3292    frame.instruction = 0x3d84;
  3293 -  current_registers["$edi"] = 0x64061449U;
  3294 +  current_registers[ustr__ZSedi()] = 0x64061449U;
  3295    cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
  3296    ASSERT_TRUE(cfi_frame_info.get());
  3297    ASSERT_TRUE(cfi_frame_info.get()
  3298                ->FindCallerRegs<uint32_t>(current_registers, memory,
  3299                                            &caller_registers));
  3300    VerifyRegisters(__FILE__, __LINE__,
  3301                    expected_caller_registers, caller_registers);
  3303 diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h
  3304 --- a/src/processor/postfix_evaluator-inl.h
  3305 +++ b/src/processor/postfix_evaluator-inl.h
  3306 @@ -51,23 +51,25 @@
  3307  namespace google_breakpad {
  3309  using std::istringstream;
  3310  using std::ostringstream;
  3313  // A small class used in Evaluate to make sure to clean up the stack
  3314  // before returning failure.
  3315 +template<typename ValueType>
  3316  class AutoStackClearer {
  3317   public:
  3318 -  explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {}
  3319 +  explicit AutoStackClearer(vector<StackElem<ValueType> > *stack)
  3320 +    : stack_(stack) {}
  3321    ~AutoStackClearer() { stack_->clear(); }
  3323   private:
  3324 -  vector<string> *stack_;
  3325 +  vector<StackElem<ValueType> > *stack_;
  3326  };
  3329  template<typename ValueType>
  3330  bool PostfixEvaluator<ValueType>::EvaluateToken(
  3331      const string &token,
  3332      const string &expression,
  3333      DictionaryValidityType *assigned) {
  3334 @@ -170,38 +172,57 @@
  3335        BPLOG(INFO) << "Could not PopValue to get value to assign: " <<
  3336                       expression;
  3337        return false;
  3340      // Assignment is only meaningful when assigning into an identifier.
  3341      // The identifier must name a variable, not a constant.  Variables
  3342      // begin with '$'.
  3343 -    string identifier;
  3344 +    const UniqueString* identifier;
  3345      if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) {
  3346        BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an "
  3347                        "identifier is needed to assign " <<
  3348                        HexString(value) << ": " << expression;
  3349        return false;
  3351 -    if (identifier.empty() || identifier[0] != '$') {
  3352 +    if (identifier == ustr__empty() || Index(identifier,0) != '$') {
  3353        BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " <<
  3354                        identifier << ": " << expression;
  3355        return false;
  3358      (*dictionary_)[identifier] = value;
  3359      if (assigned)
  3360        (*assigned)[identifier] = true;
  3361    } else {
  3362 -    // The token is not an operator, it's a literal value or an identifier.
  3363 -    // Push it onto the stack as-is.  Use push_back instead of PushValue
  3364 -    // because PushValue pushes ValueType as a string, but token is already
  3365 -    // a string.
  3366 -    stack_.push_back(token);
  3367 +    // Push it onto the stack as-is, but first convert it either to a
  3368 +    // ValueType (if a literal) or to a UniqueString* (if an identifier).
  3369 +    //
  3370 +    // First, try to treat the value as a literal. Literals may have leading
  3371 +    // '-' sign, and the entire remaining string must be parseable as
  3372 +    // ValueType. If this isn't possible, it can't be a literal, so treat it
  3373 +    // as an identifier instead.
  3374 +    //
  3375 +    // Some versions of the libstdc++, the GNU standard C++ library, have
  3376 +    // stream extractors for unsigned integer values that permit a leading
  3377 +    // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we
  3378 +    // handle it explicitly here.
  3379 +    istringstream token_stream(token);
  3380 +    ValueType literal = ValueType();
  3381 +    bool negative = false;
  3382 +    if (token_stream.peek() == '-') {
  3383 +      negative = true;
  3384 +      token_stream.get();
  3385 +    }
  3386 +    if (token_stream >> literal && token_stream.peek() == EOF) {
  3387 +      PushValue(negative ? (-literal) : literal);
  3388 +    } else {
  3389 +      PushIdentifier(ToUniqueString(token));
  3390 +    }
  3392    return true;
  3395  template<typename ValueType>
  3396  bool PostfixEvaluator<ValueType>::EvaluateInternal(
  3397      const string &expression,
  3398      DictionaryValidityType *assigned) {
  3399 @@ -236,17 +257,17 @@
  3400    // The expression is being exevaluated only for its side effects.  Skip
  3401    // expressions that denote values only.
  3402    if (expr.how_ != Module::kExprPostfix) {
  3403      BPLOG(ERROR) << "Can't evaluate for side-effects: " << expr;
  3404      return false;
  3407    // Ensure that the stack is cleared before returning.
  3408 -  AutoStackClearer clearer(&stack_);
  3409 +  AutoStackClearer<ValueType> clearer(&stack_);
  3411    if (!EvaluateInternal(expr.postfix_, assigned))
  3412      return false;
  3414    // If there's anything left on the stack, it indicates incomplete execution.
  3415    // This is a failure case.  If the stack is empty, evalution was complete
  3416    // and successful.
  3417    if (stack_.empty())
  3418 @@ -260,17 +281,17 @@
  3419  bool PostfixEvaluator<ValueType>::EvaluateForValue(const Module::Expr& expr,
  3420                                                     ValueType* result) {
  3421    switch (expr.how_) {
  3423      // Postfix expression.  Give to the evaluator and return the
  3424      // one-and-only stack element that should be left over.
  3425      case Module::kExprPostfix: {
  3426        // Ensure that the stack is cleared before returning.
  3427 -      AutoStackClearer clearer(&stack_);
  3428 +      AutoStackClearer<ValueType> clearer(&stack_);
  3430        if (!EvaluateInternal(expr.postfix_, NULL))
  3431          return false;
  3433        // A successful execution should leave exactly one value on the stack.
  3434        if (stack_.size() != 1) {
  3435          BPLOG(ERROR) << "Expression yielded bad number of results: "
  3436                       << "'" << expr << "'";
  3437 @@ -314,77 +335,56 @@
  3438        return false;
  3443  template<typename ValueType>
  3444  typename PostfixEvaluator<ValueType>::PopResult
  3445  PostfixEvaluator<ValueType>::PopValueOrIdentifier(
  3446 -    ValueType *value, string *identifier) {
  3447 +    ValueType *value, const UniqueString** identifier) {
  3448    // There needs to be at least one element on the stack to pop.
  3449    if (!stack_.size())
  3450      return POP_RESULT_FAIL;
  3452 -  string token = stack_.back();
  3453 +  StackElem<ValueType> el = stack_.back();
  3454    stack_.pop_back();
  3456 -  // First, try to treat the value as a literal. Literals may have leading
  3457 -  // '-' sign, and the entire remaining string must be parseable as
  3458 -  // ValueType. If this isn't possible, it can't be a literal, so treat it
  3459 -  // as an identifier instead.
  3460 -  //
  3461 -  // Some versions of the libstdc++, the GNU standard C++ library, have
  3462 -  // stream extractors for unsigned integer values that permit a leading
  3463 -  // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we
  3464 -  // handle it explicitly here.
  3465 -  istringstream token_stream(token);
  3466 -  ValueType literal = ValueType();
  3467 -  bool negative;
  3468 -  if (token_stream.peek() == '-') {
  3469 -    negative = true;
  3470 -    token_stream.get();
  3471 -  } else {
  3472 -    negative = false;
  3473 -  }
  3474 -  if (token_stream >> literal && token_stream.peek() == EOF) {
  3475 -    if (value) {
  3476 -      *value = literal;
  3477 -    }
  3478 -    if (negative)
  3479 -      *value = -*value;
  3480 +  if (el.isValue) {
  3481 +    if (value)
  3482 +      *value = el.u.val;
  3483      return POP_RESULT_VALUE;
  3484    } else {
  3485 -    if (identifier) {
  3486 -      *identifier = token;
  3487 -    }
  3488 +    if (identifier)
  3489 +      *identifier = el.u.ustr;
  3490      return POP_RESULT_IDENTIFIER;
  3495  template<typename ValueType>
  3496  bool PostfixEvaluator<ValueType>::PopValue(ValueType *value) {
  3497    ValueType literal = ValueType();
  3498 -  string token;
  3499 +  const UniqueString* token;
  3500    PopResult result;
  3501    if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) {
  3502      return false;
  3503    } else if (result == POP_RESULT_VALUE) {
  3504      // This is the easy case.
  3505      *value = literal;
  3506    } else {  // result == POP_RESULT_IDENTIFIER
  3507      // There was an identifier at the top of the stack.  Resolve it to a
  3508      // value by looking it up in the dictionary.
  3509      typename DictionaryType::const_iterator iterator =
  3510          dictionary_->find(token);
  3511      if (iterator == dictionary_->end()) {
  3512        // The identifier wasn't found in the dictionary.  Don't imply any
  3513        // default value, just fail.
  3514 -      BPLOG(INFO) << "Identifier " << token << " not in dictionary";
  3515 +      BPLOG(INFO) << "Identifier " << FromUniqueString(token)
  3516 +                  << " not in dictionary";
  3517        return false;
  3520      *value = iterator->second;
  3523    return true;
  3525 @@ -394,18 +394,23 @@
  3526  bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1,
  3527                                              ValueType *value2) {
  3528    return PopValue(value2) && PopValue(value1);
  3532  template<typename ValueType>
  3533  void PostfixEvaluator<ValueType>::PushValue(const ValueType &value) {
  3534 -  ostringstream token_stream;
  3535 -  token_stream << value;
  3536 -  stack_.push_back(token_stream.str());
  3537 +  StackElem<ValueType> el(value);
  3538 +  stack_.push_back(el);
  3539 +}
  3541 +template<typename ValueType>
  3542 +void PostfixEvaluator<ValueType>::PushIdentifier(const UniqueString* str) {
  3543 +  StackElem<ValueType> el(str);
  3544 +  stack_.push_back(el);
  3548  }  // namespace google_breakpad
  3551  #endif  // PROCESSOR_POSTFIX_EVALUATOR_INL_H__
  3552 diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
  3553 --- a/src/processor/postfix_evaluator.h
  3554 +++ b/src/processor/postfix_evaluator.h
  3555 @@ -70,30 +70,41 @@
  3556  #define PROCESSOR_POSTFIX_EVALUATOR_H__
  3559  #include <map>
  3560  #include <string>
  3561  #include <vector>
  3563  #include "common/using_std_string.h"
  3564 +#include "common/unique_string.h"
  3565  #include "common/module.h"
  3567  namespace google_breakpad {
  3569  using std::map;
  3570  using std::vector;
  3572  class MemoryRegion;
  3574 +// A union type for elements in the postfix evaluator's stack.
  3575 +template<typename ValueType>
  3576 +class StackElem {
  3577 + public:
  3578 +  StackElem(ValueType val) { isValue = true; u.val = val; }
  3579 +  StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; }
  3580 +  bool isValue;
  3581 +  union { ValueType val; const UniqueString* ustr; } u;
  3582 +};
  3584  template<typename ValueType>
  3585  class PostfixEvaluator {
  3586   public:
  3587 -  typedef map<string, ValueType> DictionaryType;
  3588 -  typedef map<string, bool> DictionaryValidityType;
  3589 +  typedef map<const UniqueString*, ValueType> DictionaryType;
  3590 +  typedef map<const UniqueString*, bool> DictionaryValidityType;
  3592    // Create a PostfixEvaluator object that may be used (with Evaluate) on
  3593    // one or more expressions.  PostfixEvaluator does not take ownership of
  3594    // either argument.  |memory| may be NULL, in which case dereferencing
  3595    // (^) will not be supported.  |dictionary| may be NULL, but evaluation
  3596    // will fail in that case unless set_dictionary is used before calling
  3597    // Evaluate.
  3598    PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory)
  3599 @@ -128,24 +139,28 @@
  3600    };
  3602    // Retrieves the topmost literal value, constant, or variable from the
  3603    // stack.  Returns POP_RESULT_VALUE if the topmost entry is a literal
  3604    // value, and sets |value| accordingly.  Returns POP_RESULT_IDENTIFIER
  3605    // if the topmost entry is a constant or variable identifier, and sets
  3606    // |identifier| accordingly.  Returns POP_RESULT_FAIL on failure, such
  3607    // as when the stack is empty.
  3608 -  PopResult PopValueOrIdentifier(ValueType *value, string *identifier);
  3609 +  PopResult PopValueOrIdentifier(ValueType *value,
  3610 +                                 const UniqueString** identifier);
  3612    // Retrieves the topmost value on the stack.  If the topmost entry is
  3613    // an identifier, the dictionary is queried for the identifier's value.
  3614    // Returns false on failure, such as when the stack is empty or when
  3615    // a nonexistent identifier is named.
  3616    bool PopValue(ValueType *value);
  3618 +  // Pushes a UniqueString* on the stack.
  3619 +  void PushIdentifier(const UniqueString* ustr);
  3621    // Retrieves the top two values on the stack, in the style of PopValue.
  3622    // value2 is popped before value1, so that value1 corresponds to the
  3623    // entry that was pushed prior to value2.  Returns false on failure.
  3624    bool PopValues(ValueType *value1, ValueType *value2);
  3626    // Pushes a new value onto the stack.
  3627    void PushValue(const ValueType &value);
  3629 @@ -166,15 +181,15 @@
  3631    // If non-NULL, the MemoryRegion used for dereference (^) operations.
  3632    // If NULL, dereferencing is unsupported and will fail.  Weak pointer.
  3633    const MemoryRegion *memory_;
  3635    // The stack contains state information as execution progresses.  Values
  3636    // are pushed on to it as the expression string is read and as operations
  3637    // yield values; values are popped when used as operands to operators.
  3638 -  vector<string> stack_;
  3639 +  vector<StackElem<ValueType> > stack_;
  3640  };
  3642  }  // namespace google_breakpad
  3645  #endif  // PROCESSOR_POSTFIX_EVALUATOR_H__
  3646 diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
  3647 --- a/src/processor/postfix_evaluator_unittest.cc
  3648 +++ b/src/processor/postfix_evaluator_unittest.cc
  3649 @@ -43,18 +43,32 @@
  3650  #include "google_breakpad/processor/memory_region.h"
  3651  #include "processor/logging.h"
  3654  namespace {
  3657  using std::map;
  3658 +using google_breakpad::FromUniqueString;
  3659  using google_breakpad::MemoryRegion;
  3660  using google_breakpad::PostfixEvaluator;
  3661 +using google_breakpad::ToUniqueString;
  3662 +using google_breakpad::UniqueString;
  3663 +using google_breakpad::ustr__ZDcbParams;
  3664 +using google_breakpad::ustr__ZDcbSavedRegs;
  3665 +using google_breakpad::ustr__ZDcfa;
  3666 +using google_breakpad::ustr__ZDra;
  3667 +using google_breakpad::ustr__ZDraSearchStart;
  3668 +using google_breakpad::ustr__ZSebx;
  3669 +using google_breakpad::ustr__ZSebp;
  3670 +using google_breakpad::ustr__ZSedi;
  3671 +using google_breakpad::ustr__ZSeip;
  3672 +using google_breakpad::ustr__ZSesi;
  3673 +using google_breakpad::ustr__ZSesp;
  3676  // FakeMemoryRegion is used to test PostfixEvaluator's dereference (^)
  3677  // operator.  The result of dereferencing a value is one greater than
  3678  // the value.
  3679  class FakeMemoryRegion : public MemoryRegion {
  3680   public:
  3681    virtual uint64_t GetBase() const { return 0; }
  3682 @@ -95,17 +109,17 @@
  3683    // The list of tests.
  3684    const EvaluateTest *evaluate_tests;
  3686    // The number of tests.
  3687    unsigned int evaluate_test_count;
  3689    // Identifiers and their expected values upon completion of the Evaluate
  3690    // tests in the set.
  3691 -  map<string, unsigned int> *validate_data;
  3692 +  map<const UniqueString*, unsigned int> *validate_data;
  3693  };
  3696  struct EvaluateForValueTest {
  3697    // Expression passed to PostfixEvaluator::Evaluate.
  3698    const string expression;
  3700    // True if the expression is expected to be evaluable, false if evaluation
  3701 @@ -147,39 +161,39 @@
  3702      { "$rMul 9 6 * =",     true },   // $rMul = 9 * 6 = 54
  3703      { "$rSub 9 6 - =",     true },   // $rSub = 9 - 6 = 3
  3704      { "$rDivQ 9 6 / =",    true },   // $rDivQ = 9 / 6 = 1
  3705      { "$rDivM 9 6 % =",    true },   // $rDivM = 9 % 6 = 3
  3706      { "$rDeref 9 ^ =",     true },   // $rDeref = ^9 = 10 (FakeMemoryRegion)
  3707      { "$rAlign 36 8 @ =",  true },   // $rAlign = 36 @ 8
  3708      { "$rAdd3 2 2 + =$rMul2 9 6 * =", true } // smashed-equals tokenization
  3709    };
  3710 -  map<string, unsigned int> validate_data_0;
  3711 -  validate_data_0["$rAdd"]   = 8;
  3712 -  validate_data_0["$rAdd2"]  = 4;
  3713 -  validate_data_0["$rSub"]   = 3;
  3714 -  validate_data_0["$rMul"]   = 54;
  3715 -  validate_data_0["$rDivQ"]  = 1;
  3716 -  validate_data_0["$rDivM"]  = 3;
  3717 -  validate_data_0["$rDeref"] = 10;
  3718 -  validate_data_0["$rAlign"] = 32;
  3719 -  validate_data_0["$rAdd3"]  = 4;
  3720 -  validate_data_0["$rMul2"]  = 54;
  3721 +  map<const UniqueString*, unsigned int> validate_data_0;
  3722 +  validate_data_0[ToUniqueString("$rAdd")]   = 8;
  3723 +  validate_data_0[ToUniqueString("$rAdd2")]  = 4;
  3724 +  validate_data_0[ToUniqueString("$rSub")]   = 3;
  3725 +  validate_data_0[ToUniqueString("$rMul")]   = 54;
  3726 +  validate_data_0[ToUniqueString("$rDivQ")]  = 1;
  3727 +  validate_data_0[ToUniqueString("$rDivM")]  = 3;
  3728 +  validate_data_0[ToUniqueString("$rDeref")] = 10;
  3729 +  validate_data_0[ToUniqueString("$rAlign")] = 32;
  3730 +  validate_data_0[ToUniqueString("$rAdd3")]  = 4;
  3731 +  validate_data_0[ToUniqueString("$rMul2")]  = 54;
  3733    // The second test set simulates a couple of MSVC program strings.
  3734    // The data is fudged a little bit because the tests use FakeMemoryRegion
  3735    // instead of a real stack snapshot, but the program strings are real and
  3736    // the implementation doesn't know or care that the data is not real.
  3737    PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
  3738 -  dictionary_1["$ebp"] = 0xbfff0010;
  3739 -  dictionary_1["$eip"] = 0x10000000;
  3740 -  dictionary_1["$esp"] = 0xbfff0000;
  3741 -  dictionary_1[".cbSavedRegs"] = 4;
  3742 -  dictionary_1[".cbParams"] = 4;
  3743 -  dictionary_1[".raSearchStart"] = 0xbfff0020;
  3744 +  dictionary_1[ustr__ZSebp()] = 0xbfff0010;
  3745 +  dictionary_1[ustr__ZSeip()] = 0x10000000;
  3746 +  dictionary_1[ustr__ZSesp()] = 0xbfff0000;
  3747 +  dictionary_1[ustr__ZDcbSavedRegs()] = 4;
  3748 +  dictionary_1[ustr__ZDcbParams()] = 4;
  3749 +  dictionary_1[ustr__ZDraSearchStart()] = 0xbfff0020;
  3750    const EvaluateTest evaluate_tests_1[] = {
  3751      { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
  3752        "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
  3753      // Intermediate state: $T0  = 0xbfff0010, $eip = 0xbfff0015,
  3754      //                     $ebp = 0xbfff0011, $esp = 0xbfff0018,
  3755      //                     $L   = 0xbfff000c, $P   = 0xbfff001c
  3756      { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
  3757        "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =",
  3758 @@ -188,28 +202,28 @@
  3759      //                     $ebp = 0xbfff0012, $esp = 0xbfff0019,
  3760      //                     $L   = 0xbfff000d, $P   = 0xbfff001d,
  3761      //                     $ebx = 0xbffefff6
  3762      { "$T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = "
  3763        "$esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = "
  3764        "$ebx $T0 28 - ^ =",
  3765        true }
  3766    };
  3767 -  map<string, unsigned int> validate_data_1;
  3768 -  validate_data_1["$T0"]  = 0xbfff0012;
  3769 -  validate_data_1["$T1"]  = 0xbfff0020;
  3770 -  validate_data_1["$T2"]  = 0xbfff0019;
  3771 -  validate_data_1["$eip"] = 0xbfff0021;
  3772 -  validate_data_1["$ebp"] = 0xbfff0012;
  3773 -  validate_data_1["$esp"] = 0xbfff0024;
  3774 -  validate_data_1["$L"]   = 0xbfff000e;
  3775 -  validate_data_1["$P"]   = 0xbfff0028;
  3776 -  validate_data_1["$ebx"] = 0xbffefff7;
  3777 -  validate_data_1[".cbSavedRegs"] = 4;
  3778 -  validate_data_1[".cbParams"] = 4;
  3779 +  map<const UniqueString*, unsigned int> validate_data_1;
  3780 +  validate_data_1[ToUniqueString("$T0")]  = 0xbfff0012;
  3781 +  validate_data_1[ToUniqueString("$T1")]  = 0xbfff0020;
  3782 +  validate_data_1[ToUniqueString("$T2")]  = 0xbfff0019;
  3783 +  validate_data_1[ustr__ZSeip()] = 0xbfff0021;
  3784 +  validate_data_1[ustr__ZSebp()] = 0xbfff0012;
  3785 +  validate_data_1[ustr__ZSesp()] = 0xbfff0024;
  3786 +  validate_data_1[ToUniqueString("$L")]   = 0xbfff000e;
  3787 +  validate_data_1[ToUniqueString("$P")]   = 0xbfff0028;
  3788 +  validate_data_1[ustr__ZSebx()] = 0xbffefff7;
  3789 +  validate_data_1[ustr__ZDcbSavedRegs()] = 4;
  3790 +  validate_data_1[ustr__ZDcbParams()] = 4;
  3792    EvaluateTestSet evaluate_test_sets[] = {
  3793      { &dictionary_0, evaluate_tests_0,
  3794            sizeof(evaluate_tests_0) / sizeof(EvaluateTest), &validate_data_0 },
  3795      { &dictionary_1, evaluate_tests_1,
  3796            sizeof(evaluate_tests_1) / sizeof(EvaluateTest), &validate_data_1 },
  3797    };
  3799 @@ -251,97 +265,100 @@
  3800                  evaluate_test->expression.c_str(),
  3801                  evaluate_test->evaluable ? "evaluable" : "not evaluable",
  3802                  result ? "evaluted" : "not evaluated");
  3803          return false;
  3807      // Validate the results.
  3808 -    for (map<string, unsigned int>::const_iterator validate_iterator =
  3809 +    for (map<const UniqueString*, unsigned int>::const_iterator
  3810 +            validate_iterator =
  3811              evaluate_test_set->validate_data->begin();
  3812          validate_iterator != evaluate_test_set->validate_data->end();
  3813          ++validate_iterator) {
  3814 -      const string identifier = validate_iterator->first;
  3815 +      const UniqueString* identifier = validate_iterator->first;
  3816        unsigned int expected_value = validate_iterator->second;
  3818 -      map<string, unsigned int>::const_iterator dictionary_iterator =
  3819 +      map<const UniqueString*, unsigned int>::const_iterator
  3820 +          dictionary_iterator =
  3821            evaluate_test_set->dictionary->find(identifier);
  3823        // The identifier must exist in the dictionary.
  3824        if (dictionary_iterator == evaluate_test_set->dictionary->end()) {
  3825          fprintf(stderr, "FAIL: evaluate test set %d/%d, "
  3826                          "validate identifier \"%s\", "
  3827                          "expected %d, observed not found\n",
  3828                  evaluate_test_set_index, evaluate_test_set_count,
  3829 -                identifier.c_str(), expected_value);
  3830 +                FromUniqueString(identifier), expected_value);
  3831          return false;
  3834        // The value in the dictionary must be the same as the expected value.
  3835        unsigned int observed_value = dictionary_iterator->second;
  3836        if (expected_value != observed_value) {
  3837          fprintf(stderr, "FAIL: evaluate test set %d/%d, "
  3838                          "validate identifier \"%s\", "
  3839                          "expected %d, observed %d\n",
  3840                  evaluate_test_set_index, evaluate_test_set_count,
  3841 -                identifier.c_str(), expected_value, observed_value);
  3842 +                FromUniqueString(identifier), expected_value, observed_value);
  3843          return false;
  3846        // The value must be set in the "assigned" dictionary if it was a
  3847        // variable.  It must not have been assigned if it was a constant.
  3848 -      bool expected_assigned = identifier[0] == '$';
  3849 +      bool expected_assigned = FromUniqueString(identifier)[0] == '$';
  3850        bool observed_assigned = false;
  3851        PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator
  3852            iterator_assigned = assigned.find(identifier);
  3853        if (iterator_assigned != assigned.end()) {
  3854          observed_assigned = iterator_assigned->second;
  3856        if (expected_assigned != observed_assigned) {
  3857          fprintf(stderr, "FAIL: evaluate test set %d/%d, "
  3858                          "validate assignment of \"%s\", "
  3859                          "expected %d, observed %d\n",
  3860                  evaluate_test_set_index, evaluate_test_set_count,
  3861 -                identifier.c_str(), expected_assigned, observed_assigned);
  3862 +                FromUniqueString(identifier), expected_assigned,
  3863 +                observed_assigned);
  3864          return false;
  3869    // EvaluateForValue tests.
  3870    PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
  3871 -  dictionary_2["$ebp"] = 0xbfff0010;
  3872 -  dictionary_2["$eip"] = 0x10000000;
  3873 -  dictionary_2["$esp"] = 0xbfff0000;
  3874 -  dictionary_2[".cbSavedRegs"] = 4;
  3875 -  dictionary_2[".cbParams"] = 4;
  3876 -  dictionary_2[".raSearchStart"] = 0xbfff0020;
  3877 +  dictionary_2[ustr__ZSebp()] = 0xbfff0010;
  3878 +  dictionary_2[ustr__ZSeip()] = 0x10000000;
  3879 +  dictionary_2[ustr__ZSesp()] = 0xbfff0000;
  3880 +  dictionary_2[ustr__ZDcbSavedRegs()] = 4;
  3881 +  dictionary_2[ustr__ZDcbParams()] = 4;
  3882 +  dictionary_2[ustr__ZDraSearchStart()] = 0xbfff0020;
  3883    const EvaluateForValueTest evaluate_for_value_tests_2[] = {
  3884      { "28907223",               true,  28907223 },      // simple constant
  3885      { "89854293 40010015 +",    true,  89854293 + 40010015 }, // arithmetic
  3886      { "-870245 8769343 +",      true,  7899098 },       // negative constants
  3887      { "$ebp $esp - $eip +",     true,  0x10000010 },    // variable references
  3888      { "18929794 34015074",      false, 0 },             // too many values
  3889      { "$ebp $ebp 4 - =",        false, 0 },             // too few values
  3890      { "$new $eip = $new",       true,  0x10000000 },    // make new variable
  3891      { "$new 4 +",               true,  0x10000004 },    // see prior assignments
  3892      { ".cfa 42 = 10",           false, 0 }              // can't set constants
  3893    };
  3894    const int evaluate_for_value_tests_2_size
  3895        = (sizeof (evaluate_for_value_tests_2)
  3896           / sizeof (evaluate_for_value_tests_2[0]));
  3897 -  map<string, unsigned int> validate_data_2;
  3898 -  validate_data_2["$eip"] = 0x10000000;
  3899 -  validate_data_2["$ebp"] = 0xbfff000c;
  3900 -  validate_data_2["$esp"] = 0xbfff0000;
  3901 -  validate_data_2["$new"] = 0x10000000;
  3902 -  validate_data_2[".cbSavedRegs"] = 4;
  3903 -  validate_data_2[".cbParams"] = 4;
  3904 -  validate_data_2[".raSearchStart"] = 0xbfff0020;
  3905 +  map<const UniqueString*, unsigned int> validate_data_2;
  3906 +  validate_data_2[ustr__ZSeip()] = 0x10000000;
  3907 +  validate_data_2[ustr__ZSebp()] = 0xbfff000c;
  3908 +  validate_data_2[ustr__ZSesp()] = 0xbfff0000;
  3909 +  validate_data_2[ToUniqueString("$new")] = 0x10000000;
  3910 +  validate_data_2[ustr__ZDcbSavedRegs()] = 4;
  3911 +  validate_data_2[ustr__ZDcbParams()] = 4;
  3912 +  validate_data_2[ustr__ZDraSearchStart()] = 0xbfff0020;
  3914    postfix_evaluator.set_dictionary(&dictionary_2);
  3915    for (int i = 0; i < evaluate_for_value_tests_2_size; i++) {
  3916      const EvaluateForValueTest *test = &evaluate_for_value_tests_2[i];
  3917      unsigned int result;
  3918      if (postfix_evaluator.EvaluateForValue(test->expression, &result)
  3919          != test->evaluable) {
  3920        fprintf(stderr, "FAIL: evaluate for value test %d, "
  3921 @@ -353,40 +370,43 @@
  3922      if (test->evaluable && result != test->value) {
  3923        fprintf(stderr, "FAIL: evaluate for value test %d, "
  3924                "expected value to be 0x%x, but it was 0x%x\n",
  3925                i, test->value, result);
  3926        return false;
  3930 -  for (map<string, unsigned int>::iterator v = validate_data_2.begin();
  3931 +  for (map<const UniqueString*, unsigned int>::iterator v =
  3932 +         validate_data_2.begin();
  3933         v != validate_data_2.end(); v++) {
  3934 -    map<string, unsigned int>::iterator a = dictionary_2.find(v->first);
  3935 +    map<const UniqueString*, unsigned int>::iterator a =
  3936 +        dictionary_2.find(v->first);
  3937      if (a == dictionary_2.end()) {
  3938        fprintf(stderr, "FAIL: evaluate for value dictionary check: "
  3939                "expected dict[\"%s\"] to be 0x%x, but it was unset\n",
  3940 -              v->first.c_str(), v->second);
  3941 +              FromUniqueString(v->first), v->second);
  3942        return false;
  3943      } else if (a->second != v->second) {
  3944        fprintf(stderr, "FAIL: evaluate for value dictionary check: "
  3945                "expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
  3946 -              v->first.c_str(), v->second, a->second);
  3947 +              FromUniqueString(v->first), v->second, a->second);
  3948        return false;
  3950      dictionary_2.erase(a);
  3953 -  map<string, unsigned int>::iterator remaining = dictionary_2.begin();
  3954 +  map<const UniqueString*, unsigned int>::iterator remaining =
  3955 +      dictionary_2.begin();
  3956    if (remaining != dictionary_2.end()) {
  3957      fprintf(stderr, "FAIL: evaluation of test expressions put unexpected "
  3958              "values in dictionary:\n");
  3959      for (; remaining != dictionary_2.end(); remaining++)
  3960        fprintf(stderr, "    dict[\"%s\"] == 0x%x\n",
  3961 -              remaining->first.c_str(), remaining->second);
  3962 +              FromUniqueString(remaining->first), remaining->second);
  3963      return false;
  3966    return true;
  3970  }  // namespace
  3971 diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc
  3972 --- a/src/processor/stackwalker_amd64.cc
  3973 +++ b/src/processor/stackwalker_amd64.cc
  3974 @@ -50,49 +50,49 @@
  3976  const StackwalkerAMD64::CFIWalker::RegisterSet
  3977  StackwalkerAMD64::cfi_register_map_[] = {
  3978    // It may seem like $rip and $rsp are callee-saves, because the callee is
  3979    // responsible for having them restored upon return. But the callee_saves
  3980    // flags here really means that the walker should assume they're
  3981    // unchanged if the CFI doesn't mention them --- clearly wrong for $rip
  3982    // and $rsp.
  3983 -  { "$rax", NULL, false,
  3984 +  { ToUniqueString("$rax"), NULL, false,
  3985      StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax },
  3986 -  { "$rdx", NULL, false,
  3987 +  { ToUniqueString("$rdx"), NULL, false,
  3988      StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx },
  3989 -  { "$rcx", NULL, false,
  3990 +  { ToUniqueString("$rcx"), NULL, false,
  3991      StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx },
  3992 -  { "$rbx", NULL, true,
  3993 +  { ToUniqueString("$rbx"), NULL, true,
  3994      StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx },
  3995 -  { "$rsi", NULL, false,
  3996 +  { ToUniqueString("$rsi"), NULL, false,
  3997      StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi },
  3998 -  { "$rdi", NULL, false,
  3999 +  { ToUniqueString("$rdi"), NULL, false,
  4000      StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi },
  4001 -  { "$rbp", NULL, true,
  4002 +  { ToUniqueString("$rbp"), NULL, true,
  4003      StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp },
  4004 -  { "$rsp", ".cfa", false,
  4005 +  { ToUniqueString("$rsp"), ToUniqueString(".cfa"), false,
  4006      StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp },
  4007 -  { "$r8", NULL, false,
  4008 +  { ToUniqueString("$r8"), NULL, false,
  4009      StackFrameAMD64::CONTEXT_VALID_R8,  &MDRawContextAMD64::r8 },
  4010 -  { "$r9", NULL, false,
  4011 +  { ToUniqueString("$r9"), NULL, false,
  4012      StackFrameAMD64::CONTEXT_VALID_R9,  &MDRawContextAMD64::r9 },
  4013 -  { "$r10", NULL, false,
  4014 +  { ToUniqueString("$r10"), NULL, false,
  4015      StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 },
  4016 -  { "$r11", NULL, false,
  4017 +  { ToUniqueString("$r11"), NULL, false,
  4018      StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 },
  4019 -  { "$r12", NULL, true,
  4020 +  { ToUniqueString("$r12"), NULL, true,
  4021      StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 },
  4022 -  { "$r13", NULL, true,
  4023 +  { ToUniqueString("$r13"), NULL, true,
  4024      StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 },
  4025 -  { "$r14", NULL, true,
  4026 +  { ToUniqueString("$r14"), NULL, true,
  4027      StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 },
  4028 -  { "$r15", NULL, true,
  4029 +  { ToUniqueString("$r15"), NULL, true,
  4030      StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 },
  4031 -  { "$rip", ".ra", false,
  4032 +  { ToUniqueString("$rip"), ToUniqueString(".ra"), false,
  4033      StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip },
  4034  };
  4036  StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info,
  4037                                     const MDRawContextAMD64* context,
  4038                                     MemoryRegion* memory,
  4039                                     const CodeModules* modules,
  4040                                     StackFrameSymbolizer* resolver_helper)
  4041 diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
  4042 --- a/src/processor/stackwalker_arm.cc
  4043 +++ b/src/processor/stackwalker_arm.cc
  4044 @@ -76,21 +76,30 @@
  4045    return frame;
  4048  StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo(
  4049      const vector<StackFrame*> &frames,
  4050      CFIFrameInfo* cfi_frame_info) {
  4051    StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
  4053 -  static const char* register_names[] = {
  4054 -    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
  4055 -    "r8",  "r9",  "r10", "r11", "r12", "sp",  "lr",  "pc",
  4056 -    "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
  4057 -    "fps", "cpsr",
  4058 +  static const UniqueString *register_names[] = {
  4059 +    ToUniqueString("r0"),  ToUniqueString("r1"),
  4060 +    ToUniqueString("r2"),  ToUniqueString("r3"),
  4061 +    ToUniqueString("r4"),  ToUniqueString("r5"),
  4062 +    ToUniqueString("r6"),  ToUniqueString("r7"),
  4063 +    ToUniqueString("r8"),  ToUniqueString("r9"),
  4064 +    ToUniqueString("r10"), ToUniqueString("r11"),
  4065 +    ToUniqueString("r12"), ToUniqueString("sp"),
  4066 +    ToUniqueString("lr"),  ToUniqueString("pc"),
  4067 +    ToUniqueString("f0"),  ToUniqueString("f1"),
  4068 +    ToUniqueString("f2"),  ToUniqueString("f3"),
  4069 +    ToUniqueString("f4"),  ToUniqueString("f5"),
  4070 +    ToUniqueString("f6"),  ToUniqueString("f7"),
  4071 +    ToUniqueString("fps"), ToUniqueString("cpsr"),
  4072      NULL
  4073    };
  4075    // Populate a dictionary with the valid register values in last_frame.
  4076    CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
  4077    for (int i = 0; register_names[i]; i++)
  4078      if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
  4079        callee_registers[register_names[i]] = last_frame->context.iregs[i];
  4080 @@ -119,17 +128,17 @@
  4081        // Call Standard for the ARM Architecture, which the Linux ABI follows.
  4082        frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
  4083        frame->context.iregs[i] = last_frame->context.iregs[i];
  4086    // If the CFI doesn't recover the PC explicitly, then use .ra.
  4087    if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
  4088      CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
  4089 -      caller_registers.find(".ra");
  4090 +      caller_registers.find(ustr__ZDra());
  4091      if (entry != caller_registers.end()) {
  4092        if (fp_register_ == -1) {
  4093          frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
  4094          frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second;
  4095        } else {
  4096          // The CFI updated the link register and not the program counter.
  4097          // Handle getting the program counter from the link register.
  4098          frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
  4099 @@ -138,17 +147,17 @@
  4100          frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
  4101              last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
  4105    // If the CFI doesn't recover the SP explicitly, then use .cfa.
  4106    if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
  4107      CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
  4108 -      caller_registers.find(".cfa");
  4109 +      caller_registers.find(ustr__ZDcfa());
  4110      if (entry != caller_registers.end()) {
  4111        frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP;
  4112        frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second;
  4116    // If we didn't recover the PC and the SP, then the frame isn't very useful.
  4117    static const int essentials = (StackFrameARM::CONTEXT_VALID_SP
  4118 diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
  4119 --- a/src/processor/stackwalker_x86.cc
  4120 +++ b/src/processor/stackwalker_x86.cc
  4121 @@ -53,33 +53,33 @@
  4123  const StackwalkerX86::CFIWalker::RegisterSet
  4124  StackwalkerX86::cfi_register_map_[] = {
  4125    // It may seem like $eip and $esp are callee-saves, because (with Unix or
  4126    // cdecl calling conventions) the callee is responsible for having them
  4127    // restored upon return. But the callee_saves flags here really means
  4128    // that the walker should assume they're unchanged if the CFI doesn't
  4129    // mention them, which is clearly wrong for $eip and $esp.
  4130 -  { "$eip", ".ra",  false,
  4131 +  { ToUniqueString("$eip"), ToUniqueString(".ra"),  false,
  4132      StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip },
  4133 -  { "$esp", ".cfa", false,
  4134 +  { ToUniqueString("$esp"), ToUniqueString(".cfa"), false,
  4135      StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp },
  4136 -  { "$ebp", NULL,   true,
  4137 +  { ToUniqueString("$ebp"), NULL,   true,
  4138      StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp },
  4139 -  { "$eax", NULL,   false,
  4140 +  { ToUniqueString("$eax"), NULL,   false,
  4141      StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax },
  4142 -  { "$ebx", NULL,   true,
  4143 +  { ToUniqueString("$ebx"), NULL,   true,
  4144      StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx },
  4145 -  { "$ecx", NULL,   false,
  4146 +  { ToUniqueString("$ecx"), NULL,   false,
  4147      StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx },
  4148 -  { "$edx", NULL,   false,
  4149 +  { ToUniqueString("$edx"), NULL,   false,
  4150      StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx },
  4151 -  { "$esi", NULL,   true,
  4152 +  { ToUniqueString("$esi"), NULL,   true,
  4153      StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi },
  4154 -  { "$edi", NULL,   true,
  4155 +  { ToUniqueString("$edi"), NULL,   true,
  4156      StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi },
  4157  };
  4159  StackwalkerX86::StackwalkerX86(const SystemInfo* system_info,
  4160                                 const MDRawContextX86* context,
  4161                                 MemoryRegion* memory,
  4162                                 const CodeModules* modules,
  4163                                 StackFrameSymbolizer* resolver_helper)
  4164 @@ -194,26 +194,26 @@
  4168    // Set up the dictionary for the PostfixEvaluator.  %ebp and %esp are used
  4169    // in each program string, and their previous values are known, so set them
  4170    // here.
  4171    PostfixEvaluator<uint32_t>::DictionaryType dictionary;
  4172    // Provide the current register values.
  4173 -  dictionary["$ebp"] = last_frame->context.ebp;
  4174 -  dictionary["$esp"] = last_frame->context.esp;
  4175 +  dictionary[ustr__ZSebp()] = last_frame->context.ebp;
  4176 +  dictionary[ustr__ZSesp()] = last_frame->context.esp;
  4177    // Provide constants from the debug info for last_frame and its callee.
  4178    // .cbCalleeParams is a Breakpad extension that allows us to use the
  4179    // PostfixEvaluator engine when certain types of debugging information
  4180    // are present without having to write the constants into the program
  4181    // string as literals.
  4182 -  dictionary[".cbCalleeParams"] = last_frame_callee_parameter_size;
  4183 -  dictionary[".cbSavedRegs"] = last_frame_info->saved_register_size;
  4184 -  dictionary[".cbLocals"] = last_frame_info->local_size;
  4185 +  dictionary[ustr__ZDcbCalleeParams()] = last_frame_callee_parameter_size;
  4186 +  dictionary[ustr__ZDcbSavedRegs()] = last_frame_info->saved_register_size;
  4187 +  dictionary[ustr__ZDcbLocals()] = last_frame_info->local_size;
  4189    uint32_t raSearchStart = last_frame->context.esp +
  4190                              last_frame_callee_parameter_size +
  4191                              last_frame_info->local_size +
  4192                              last_frame_info->saved_register_size;
  4194    uint32_t raSearchStartOld = raSearchStart;
  4195    uint32_t found = 0;  // dummy value
  4196 @@ -232,20 +232,20 @@
  4197      // Skip one slot from the stack and do another scan in order to get the
  4198      // actual return address.
  4199      raSearchStart += 4;
  4200      ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
  4203    // The difference between raSearch and raSearchStart is unknown,
  4204    // but making them the same seems to work well in practice.
  4205 -  dictionary[".raSearchStart"] = raSearchStart;
  4206 -  dictionary[".raSearch"] = raSearchStart;
  4207 +  dictionary[ustr__ZDraSearchStart()] = raSearchStart;
  4208 +  dictionary[ustr__ZDraSearch()] = raSearchStart;
  4210 -  dictionary[".cbParams"] = last_frame_info->parameter_size;
  4211 +  dictionary[ustr__ZDcbParams()] = last_frame_info->parameter_size;
  4213    // Decide what type of program string to use. The program string is in
  4214    // postfix notation and will be passed to PostfixEvaluator::Evaluate.
  4215    // Given the dictionary and the program string, it is possible to compute
  4216    // the return address and the values of other registers in the calling
  4217    // function. Because of bugs described below, the stack may need to be
  4218    // scanned for these values. The results of program string evaluation
  4219    // will be used to determine whether to scan for better values.
  4220 @@ -325,18 +325,18 @@
  4223    // Now crank it out, making sure that the program string set at least the
  4224    // two required variables.
  4225    PostfixEvaluator<uint32_t> evaluator =
  4226        PostfixEvaluator<uint32_t>(&dictionary, memory_);
  4227    PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity;
  4228    if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
  4229 -      dictionary_validity.find("$eip") == dictionary_validity.end() ||
  4230 -      dictionary_validity.find("$esp") == dictionary_validity.end()) {
  4231 +      dictionary_validity.find(ustr__ZSeip()) == dictionary_validity.end() ||
  4232 +      dictionary_validity.find(ustr__ZSesp()) == dictionary_validity.end()) {
  4233      // Program string evaluation failed. It may be that %eip is not somewhere
  4234      // with stack frame info, and %ebp is pointing to non-stack memory, so
  4235      // our evaluation couldn't succeed. We'll scan the stack for a return
  4236      // address. This can happen if the stack is in a module for which
  4237      // we don't have symbols, and that module is compiled without a
  4238      // frame pointer.
  4239      uint32_t location_start = last_frame->context.esp;
  4240      uint32_t location, eip;
  4241 @@ -344,69 +344,69 @@
  4242        // if we can't find an instruction pointer even with stack scanning,
  4243        // give up.
  4244        return NULL;
  4247      // This seems like a reasonable return address. Since program string
  4248      // evaluation failed, use it and set %esp to the location above the
  4249      // one where the return address was found.
  4250 -    dictionary["$eip"] = eip;
  4251 -    dictionary["$esp"] = location + 4;
  4252 +    dictionary[ustr__ZSeip()] = eip;
  4253 +    dictionary[ustr__ZSesp()] = location + 4;
  4254      trust = StackFrame::FRAME_TRUST_SCAN;
  4257    // Since this stack frame did not use %ebp in a traditional way,
  4258    // locating the return address isn't entirely deterministic. In that
  4259    // case, the stack can be scanned to locate the return address.
  4260    //
  4261    // However, if program string evaluation resulted in both %eip and
  4262    // %ebp values of 0, trust that the end of the stack has been
  4263    // reached and don't scan for anything else.
  4264 -  if (dictionary["$eip"] != 0 || dictionary["$ebp"] != 0) {
  4265 +  if (dictionary[ustr__ZSeip()] != 0 || dictionary[ustr__ZSebp()] != 0) {
  4266      int offset = 0;
  4268      // This scan can only be done if a CodeModules object is available, to
  4269      // check that candidate return addresses are in fact inside a module.
  4270      //
  4271      // TODO(mmentovai): This ignores dynamically-generated code.  One possible
  4272      // solution is to check the minidump's memory map to see if the candidate
  4273      // %eip value comes from a mapped executable page, although this would
  4274      // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad
  4275      // client doesn't currently write (it would need to call MiniDumpWriteDump
  4276      // with the MiniDumpWithFullMemoryInfo type bit set).  Even given this
  4277      // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
  4278      // an independent execute privilege on memory pages.
  4280 -    uint32_t eip = dictionary["$eip"];
  4281 +    uint32_t eip = dictionary[ustr__ZSeip()];
  4282      if (modules_ && !modules_->GetModuleForAddress(eip)) {
  4283        // The instruction pointer at .raSearchStart was invalid, so start
  4284        // looking one 32-bit word above that location.
  4285 -      uint32_t location_start = dictionary[".raSearchStart"] + 4;
  4286 +      uint32_t location_start = dictionary[ustr__ZDraSearchStart()] + 4;
  4287        uint32_t location;
  4288        if (ScanForReturnAddress(location_start, &location, &eip)) {
  4289          // This is a better return address that what program string
  4290          // evaluation found.  Use it, and set %esp to the location above the
  4291          // one where the return address was found.
  4292 -        dictionary["$eip"] = eip;
  4293 -        dictionary["$esp"] = location + 4;
  4294 +        dictionary[ustr__ZSeip()] = eip;
  4295 +        dictionary[ustr__ZSesp()] = location + 4;
  4296          offset = location - location_start;
  4297          trust = StackFrame::FRAME_TRUST_CFI_SCAN;
  4301      if (recover_ebp) {
  4302        // When trying to recover the previous value of the frame pointer (%ebp),
  4303        // start looking at the lowest possible address in the saved-register
  4304        // area, and look at the entire saved register area, increased by the
  4305        // size of |offset| to account for additional data that may be on the
  4306        // stack.  The scan is performed from the highest possible address to
  4307        // the lowest, because the expectation is that the function's prolog
  4308        // would have saved %ebp early.
  4309 -      uint32_t ebp = dictionary["$ebp"];
  4310 +      uint32_t ebp = dictionary[ustr__ZSebp()];
  4312        // When a scan for return address is used, it is possible to skip one or
  4313        // more frames (when return address is not in a known module).  One
  4314        // indication for skipped frames is when the value of %ebp is lower than
  4315        // the location of the return address on the stack
  4316        bool has_skipped_frames =
  4317          (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset);
  4319 @@ -420,49 +420,49 @@
  4320               location >= location_end;
  4321               location -= 4) {
  4322            if (!memory_->GetMemoryAtAddress(location, &ebp))
  4323              break;
  4325            if (memory_->GetMemoryAtAddress(ebp, &value)) {
  4326              // The candidate value is a pointer to the same memory region
  4327              // (the stack).  Prefer it as a recovered %ebp result.
  4328 -            dictionary["$ebp"] = ebp;
  4329 +            dictionary[ustr__ZSebp()] = ebp;
  4330              break;
  4337    // Create a new stack frame (ownership will be transferred to the caller)
  4338    // and fill it in.
  4339    StackFrameX86* frame = new StackFrameX86();
  4341    frame->trust = trust;
  4342    frame->context = last_frame->context;
  4343 -  frame->context.eip = dictionary["$eip"];
  4344 -  frame->context.esp = dictionary["$esp"];
  4345 -  frame->context.ebp = dictionary["$ebp"];
  4346 +  frame->context.eip = dictionary[ustr__ZSeip()];
  4347 +  frame->context.esp = dictionary[ustr__ZSesp()];
  4348 +  frame->context.ebp = dictionary[ustr__ZSebp()];
  4349    frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
  4350                                  StackFrameX86::CONTEXT_VALID_ESP |
  4351                                  StackFrameX86::CONTEXT_VALID_EBP;
  4353    // These are nonvolatile (callee-save) registers, and the program string
  4354    // may have filled them in.
  4355 -  if (dictionary_validity.find("$ebx") != dictionary_validity.end()) {
  4356 -    frame->context.ebx = dictionary["$ebx"];
  4357 +  if (dictionary_validity.find(ustr__ZSebx()) != dictionary_validity.end()) {
  4358 +    frame->context.ebx = dictionary[ustr__ZSebx()];
  4359      frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX;
  4361 -  if (dictionary_validity.find("$esi") != dictionary_validity.end()) {
  4362 -    frame->context.esi = dictionary["$esi"];
  4363 +  if (dictionary_validity.find(ustr__ZSesi()) != dictionary_validity.end()) {
  4364 +    frame->context.esi = dictionary[ustr__ZSesi()];
  4365      frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI;
  4367 -  if (dictionary_validity.find("$edi") != dictionary_validity.end()) {
  4368 -    frame->context.edi = dictionary["$edi"];
  4369 +  if (dictionary_validity.find(ustr__ZSedi()) != dictionary_validity.end()) {
  4370 +    frame->context.edi = dictionary[ustr__ZSedi()];
  4371      frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
  4374    return frame;
  4377  StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
  4378      const vector<StackFrame*> &frames,
  4379 diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
  4380 --- a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
  4381 +++ b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
  4382 @@ -98,16 +98,22 @@
  4383  		B8C5B51B1166534700D34F4E /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650430B52F6D800611104 /* macho_id.cc */; };
  4384  		B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650450B52F6D800611104 /* macho_walker.cc */; };
  4385  		B8C5B51D1166534700D34F4E /* dump_syms.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* dump_syms.mm */; };
  4386  		B8C5B51E1166534700D34F4E /* dump_syms_tool.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */; };
  4387  		B8C5B523116653BA00D34F4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
  4388  		D21F97D711CBA12300239E38 /* test_assembler_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D9116CEC0600407530 /* test_assembler_unittest.cc */; };
  4389  		D21F97D811CBA13D00239E38 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
  4390  		D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; };
  4391 +		D24997CC16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
  4392 +		D24997CD16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
  4393 +		D24997CE16B6C16800E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
  4394 +		D2499A0016B9BA6A00E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
  4395 +		D2499A0216B9BA9600E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
  4396 +		D2499A0316B9BA9D00E588C5 /* unique_string.cc in Sources */ = {isa = PBXBuildFile; fileRef = D24997CA16B6C16800E588C5 /* unique_string.cc */; };
  4397  /* End PBXBuildFile section */
  4399  /* Begin PBXContainerItemProxy section */
  4400  		8B31051411F100CF00FCF3E4 /* PBXContainerItemProxy */ = {
  4401  			isa = PBXContainerItemProxy;
  4402  			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
  4403  			proxyType = 1;
  4404  			remoteGlobalIDString = D21F97D111CBA0F200239E38;
  4405 @@ -338,16 +344,18 @@
  4406  		B89E0E741166575200DD08C9 /* macho_dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_dump; sourceTree = BUILT_PRODUCTS_DIR; };
  4407  		B89E0E9511665A6400DD08C9 /* macho_reader_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_reader_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
  4408  		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; };
  4409  		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; };
  4410  		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; };
  4411  		B8C5B5111166531A00D34F4E /* dump_syms */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dump_syms; sourceTree = BUILT_PRODUCTS_DIR; };
  4412  		B8E8CA0C1156C854009E61B2 /* byteswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byteswap.h; path = ../../../common/mac/byteswap.h; sourceTree = SOURCE_ROOT; };
  4413  		D21F97D211CBA0F200239E38 /* test_assembler_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_assembler_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
  4414 +		D24997CA16B6C16800E588C5 /* unique_string.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = unique_string.cc; path = ../../../common/unique_string.cc; sourceTree = "<group>"; };
  4415 +		D24997CB16B6C16800E588C5 /* unique_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unique_string.h; path = ../../../common/unique_string.h; sourceTree = "<group>"; };
  4416  		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; };
  4417  		F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
  4418  		F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; };
  4419  		F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; };
  4420  		F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
  4421  		F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
  4422  		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; };
  4423  /* End PBXFileReference section */
  4424 @@ -531,16 +539,18 @@
  4425  				D21F97D211CBA0F200239E38 /* test_assembler_unittest */,
  4426  			);
  4427  			name = Products;
  4428  			sourceTree = "<group>";
  4429  		};
  4430  		B88FAE1C11665FFD00407530 /* MODULE */ = {
  4431  			isa = PBXGroup;
  4432  			children = (
  4433 +				D24997CA16B6C16800E588C5 /* unique_string.cc */,
  4434 +				D24997CB16B6C16800E588C5 /* unique_string.h */,
  4435  				B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */,
  4436  				B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */,
  4437  				B88FB0D6116CEC0600407530 /* dwarf_cu_to_module_unittest.cc */,
  4438  				B88FAE201166603300407530 /* dwarf_line_to_module.cc */,
  4439  				B88FAE211166603300407530 /* dwarf_line_to_module.h */,
  4440  				B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */,
  4441  				B88FAE221166603300407530 /* language.cc */,
  4442  				B88FAE231166603300407530 /* language.h */,
  4443 @@ -940,16 +950,17 @@
  4444  		};
  4445  /* End PBXShellScriptBuildPhase section */
  4447  /* Begin PBXSourcesBuildPhase section */
  4448  		B84A91F1116CF784006C210E /* Sources */ = {
  4449  			isa = PBXSourcesBuildPhase;
  4450  			buildActionMask = 2147483647;
  4451  			files = (
  4452 +				D2499A0216B9BA9600E588C5 /* unique_string.cc in Sources */,
  4453  				B84A91FB116CF7AF006C210E /* module.cc in Sources */,
  4454  				B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */,
  4455  				B84A91FD116CF7AF006C210E /* stabs_to_module_unittest.cc in Sources */,
  4456  			);
  4457  			runOnlyForDeploymentPostprocessing = 0;
  4458  		};
  4459  		B88FAF2C116A591D00407530 /* Sources */ = {
  4460  			isa = PBXSourcesBuildPhase;
  4461 @@ -983,56 +994,60 @@
  4462  			runOnlyForDeploymentPostprocessing = 0;
  4463  		};
  4464  		B88FB0B6116CEABF00407530 /* Sources */ = {
  4465  			isa = PBXSourcesBuildPhase;
  4466  			buildActionMask = 2147483647;
  4467  			files = (
  4468  				B88FB0BD116CEAE000407530 /* module_unittest.cc in Sources */,
  4469  				B88FB0C4116CEB4100407530 /* module.cc in Sources */,
  4470 +				D24997CE16B6C16800E588C5 /* unique_string.cc in Sources */,
  4471  			);
  4472  			runOnlyForDeploymentPostprocessing = 0;
  4473  		};
  4474  		B88FB0DC116CEEA800407530 /* Sources */ = {
  4475  			isa = PBXSourcesBuildPhase;
  4476  			buildActionMask = 2147483647;
  4477  			files = (
  4478  				B88FB0E5116CEED300407530 /* dwarf2diehandler.cc in Sources */,
  4479  				B88FB0E6116CEED300407530 /* dwarf2diehandler_unittest.cc in Sources */,
  4480  			);
  4481  			runOnlyForDeploymentPostprocessing = 0;
  4482  		};
  4483  		B88FB0EF116CEF1900407530 /* Sources */ = {
  4484  			isa = PBXSourcesBuildPhase;
  4485  			buildActionMask = 2147483647;
  4486  			files = (
  4487 +				D2499A0316B9BA9D00E588C5 /* unique_string.cc in Sources */,
  4488  				B88FB0FA116CF00E00407530 /* dwarf_line_to_module.cc in Sources */,
  4489  				B88FB0FE116CF02400407530 /* module.cc in Sources */,
  4490  				B88FB0FB116CF00E00407530 /* dwarf_line_to_module_unittest.cc in Sources */,
  4491  			);
  4492  			runOnlyForDeploymentPostprocessing = 0;
  4493  		};
  4494  		B88FB107116CF07900407530 /* Sources */ = {
  4495  			isa = PBXSourcesBuildPhase;
  4496  			buildActionMask = 2147483647;
  4497  			files = (
  4498 +				D2499A0016B9BA6A00E588C5 /* unique_string.cc in Sources */,
  4499  				B88FB112116CF1F000407530 /* dwarf_cu_to_module.cc in Sources */,
  4500  				B88FB113116CF1F000407530 /* dwarf_cu_to_module_unittest.cc in Sources */,
  4501  				B88FB114116CF1F000407530 /* language.cc in Sources */,
  4502  				B88FB115116CF1F000407530 /* module.cc in Sources */,
  4503  			);
  4504  			runOnlyForDeploymentPostprocessing = 0;
  4505  		};
  4506  		B88FB11C116CF27F00407530 /* Sources */ = {
  4507  			isa = PBXSourcesBuildPhase;
  4508  			buildActionMask = 2147483647;
  4509  			files = (
  4510  				B88FB129116CF2DD00407530 /* module.cc in Sources */,
  4511  				B88FB12A116CF2DD00407530 /* dwarf_cfi_to_module.cc in Sources */,
  4512  				B88FB12B116CF2DD00407530 /* dwarf_cfi_to_module_unittest.cc in Sources */,
  4513 +				D24997CD16B6C16800E588C5 /* unique_string.cc in Sources */,
  4514  			);
  4515  			runOnlyForDeploymentPostprocessing = 0;
  4516  		};
  4517  		B88FB132116CF30F00407530 /* Sources */ = {
  4518  			isa = PBXSourcesBuildPhase;
  4519  			buildActionMask = 2147483647;
  4520  			files = (
  4521  				B88FB13D116CF38300407530 /* cfi_assembler.cc in Sources */,
  4522 @@ -1086,16 +1101,17 @@
  4523  				B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */,
  4524  				B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */,
  4525  				B88FAE281166603300407530 /* language.cc in Sources */,
  4526  				B88FAE291166603300407530 /* module.cc in Sources */,
  4527  				B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */,
  4528  				B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */,
  4529  				B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */,
  4530  				4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */,
  4531 +				D24997CC16B6C16800E588C5 /* unique_string.cc in Sources */,
  4532  			);
  4533  			runOnlyForDeploymentPostprocessing = 0;
  4534  		};
  4535  		D21F97CF11CBA0F200239E38 /* Sources */ = {
  4536  			isa = PBXSourcesBuildPhase;
  4537  			buildActionMask = 2147483647;
  4538  			files = (
  4539  				D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */,

mercurial