Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 ®) { |
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 ®) { |
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 ®); |
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 ®); |
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> ®ister_names, |
michael@0 | 981 | + DwarfCFIToModule(Module *module, |
michael@0 | 982 | + const vector<const UniqueString*> ®ister_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> ®ister_names_; |
michael@0 | 1015 | + const vector<const UniqueString*> ®ister_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 §ion) |
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 ®)); |
michael@0 | 1077 | - MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string ®)); |
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, ®ister_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 §ion, |
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> ®isters, |
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 */, |