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

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

mercurial