Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 # HG changeset patch
2 # User Ted Mielczarek <ted.mielczarek@gmail.com>
3 # Date 1360255134 18000
4 # Node ID 294ce0d64d35a90be8ea91b719ead8b82aed29f7
5 # Parent d7bfb673574a3afe8b4f76f42fb52e2545770dad
6 Rework PostfixEvaluator to use UniqueStringMap
7 Patch by Julian Seward <jseward@acm.org>, R=ted
9 diff --git a/src/common/unique_string.h b/src/common/unique_string.h
10 --- a/src/common/unique_string.h
11 +++ b/src/common/unique_string.h
12 @@ -25,16 +25,17 @@
13 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
16 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 #ifndef COMMON_UNIQUE_STRING_H_
19 #define COMMON_UNIQUE_STRING_H_
21 +#include <map>
22 #include <string>
23 #include "common/using_std_string.h"
25 namespace google_breakpad {
27 // Abstract type
28 class UniqueString;
30 @@ -229,11 +230,112 @@
32 // ".ra"
33 inline static const UniqueString* ustr__ZDra() {
34 static const UniqueString* us = NULL;
35 if (!us) us = ToUniqueString(".ra");
36 return us;
37 }
39 +template <typename ValueType>
40 +class UniqueStringMap
41 +{
42 + private:
43 + static const int N_FIXED = 10;
44 +
45 + public:
46 + UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {};
47 + ~UniqueStringMap() {};
48 +
49 + // Empty out the map.
50 + void clear() {
51 + ++n_clears_;
52 + map_.clear();
53 + n_fixed_ = 0;
54 + }
55 +
56 + // Do "map[ix] = v".
57 + void set(const UniqueString* ix, ValueType v) {
58 + ++n_sets_;
59 + int i;
60 + for (i = 0; i < n_fixed_; ++i) {
61 + if (fixed_keys_[i] == ix) {
62 + fixed_vals_[i] = v;
63 + return;
64 + }
65 + }
66 + if (n_fixed_ < N_FIXED) {
67 + i = n_fixed_;
68 + fixed_keys_[i] = ix;
69 + fixed_vals_[i] = v;
70 + ++n_fixed_;
71 + } else {
72 + map_[ix] = v;
73 + }
74 + }
75 +
76 + // Lookup 'ix' in the map, and also return a success/fail boolean.
77 + ValueType get(/*OUT*/bool* have, const UniqueString* ix) const {
78 + ++n_gets_;
79 + int i;
80 + for (i = 0; i < n_fixed_; ++i) {
81 + if (fixed_keys_[i] == ix) {
82 + *have = true;
83 + return fixed_vals_[i];
84 + }
85 + }
86 + typename std::map<const UniqueString*, ValueType>::const_iterator it
87 + = map_.find(ix);
88 + if (it == map_.end()) {
89 + *have = false;
90 + return ValueType();
91 + } else {
92 + *have = true;
93 + return it->second;
94 + }
95 + };
96 +
97 + // Lookup 'ix' in the map, and return zero if it is not present.
98 + ValueType get(const UniqueString* ix) const {
99 + ++n_gets_;
100 + bool found;
101 + ValueType v = get(&found, ix);
102 + return found ? v : ValueType();
103 + }
104 +
105 + // Find out whether 'ix' is in the map.
106 + bool have(const UniqueString* ix) const {
107 + ++n_gets_;
108 + bool found;
109 + (void)get(&found, ix);
110 + return found;
111 + }
112 +
113 + // Copy the contents to a std::map, generally for testing.
114 + void copy_to_map(std::map<const UniqueString*, ValueType>* m) const {
115 + m->clear();
116 + int i;
117 + for (i = 0; i < n_fixed_; ++i) {
118 + (*m)[fixed_keys_[i]] = fixed_vals_[i];
119 + }
120 + m->insert(map_.begin(), map_.end());
121 + }
122 +
123 + // Note that users of this class rely on having also a sane
124 + // assignment operator. The default one is OK, though.
125 + // AFAICT there are no uses of the copy constructor, but if
126 + // there were, the default one would also suffice.
127 +
128 + private:
129 + // Quick (hopefully) cache
130 + const UniqueString* fixed_keys_[N_FIXED];
131 + ValueType fixed_vals_[N_FIXED];
132 + int n_fixed_; // 0 .. N_FIXED inclusive
133 + // Fallback storage when the cache is filled
134 + std::map<const UniqueString*, ValueType> map_;
135 +
136 + // For tracking usage stats.
137 + mutable int n_sets_, n_gets_, n_clears_;
138 +};
139 +
140 } // namespace google_breakpad
142 #endif // COMMON_UNIQUE_STRING_H_
143 diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
144 --- a/src/processor/basic_source_line_resolver_unittest.cc
145 +++ b/src/processor/basic_source_line_resolver_unittest.cc
146 @@ -24,16 +24,17 @@
147 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
148 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
149 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
150 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
151 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
153 #include <stdio.h>
155 +#include <map>
156 #include <string>
158 #include "breakpad_googletest_includes.h"
159 #include "common/scoped_ptr.h"
160 #include "common/using_std_string.h"
161 #include "google_breakpad/processor/basic_source_line_resolver.h"
162 #include "google_breakpad/processor/code_module.h"
163 #include "google_breakpad/processor/stack_frame.h"
164 @@ -47,16 +48,17 @@
166 using google_breakpad::BasicSourceLineResolver;
167 using google_breakpad::CFIFrameInfo;
168 using google_breakpad::CodeModule;
169 using google_breakpad::FromUniqueString;
170 using google_breakpad::MemoryRegion;
171 using google_breakpad::StackFrame;
172 using google_breakpad::ToUniqueString;
173 +using google_breakpad::UniqueString;
174 using google_breakpad::WindowsFrameInfo;
175 using google_breakpad::linked_ptr;
176 using google_breakpad::scoped_ptr;
177 using google_breakpad::ustr__ZDcfa;
178 using google_breakpad::ustr__ZDra;
179 using google_breakpad::ustr__ZSebx;
180 using google_breakpad::ustr__ZSebp;
181 using google_breakpad::ustr__ZSedi;
182 @@ -113,27 +115,30 @@
183 };
185 // Verify that, for every association in ACTUAL, EXPECTED has the same
186 // association. (That is, ACTUAL's associations should be a subset of
187 // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
188 // ".cfa".
189 static bool VerifyRegisters(
190 const char *file, int line,
191 - const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
192 - const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
193 - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
194 + const std::map<const UniqueString*, uint32_t> &expected,
195 + const CFIFrameInfo::RegisterValueMap<uint32_t> &actual_regmap) {
196 + std::map<const UniqueString*, uint32_t> actual;
197 + actual_regmap.copy_to_map(&actual);
198 +
199 + std::map<const UniqueString*, uint32_t>::const_iterator a;
200 a = actual.find(ustr__ZDcfa());
201 if (a == actual.end())
202 return false;
203 a = actual.find(ustr__ZDra());
204 if (a == actual.end())
205 return false;
206 for (a = actual.begin(); a != actual.end(); a++) {
207 - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
208 + std::map<const UniqueString*, uint32_t>::const_iterator e =
209 expected.find(a->first);
210 if (e == expected.end()) {
211 fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
212 file, line, FromUniqueString(a->first), a->second);
213 return false;
214 }
215 if (e->second != a->second) {
216 fprintf(stderr,
217 @@ -258,86 +263,86 @@
219 frame.instruction = 0x3e9f;
220 frame.module = &module1;
221 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
222 ASSERT_FALSE(cfi_frame_info.get());
224 CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
225 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
226 - CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
227 + std::map<const UniqueString*, uint32_t> expected_caller_registers;
228 MockMemoryRegion memory;
230 // Regardless of which instruction evaluation takes place at, it
231 // should produce the same values for the caller's registers.
232 expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
233 expected_caller_registers[ustr__ZDra()] = 0xf6438648;
234 expected_caller_registers[ustr__ZSebp()] = 0x10038;
235 expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
236 expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
237 expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
239 frame.instruction = 0x3d40;
240 frame.module = &module1;
241 current_registers.clear();
242 - current_registers[ustr__ZSesp()] = 0x10018;
243 - current_registers[ustr__ZSebp()] = 0x10038;
244 - current_registers[ustr__ZSebx()] = 0x98ecadc3;
245 - current_registers[ustr__ZSesi()] = 0x878f7524;
246 - current_registers[ustr__ZSedi()] = 0x6312f9a5;
247 + current_registers.set(ustr__ZSesp(), 0x10018);
248 + current_registers.set(ustr__ZSebp(), 0x10038);
249 + current_registers.set(ustr__ZSebx(), 0x98ecadc3);
250 + current_registers.set(ustr__ZSesi(), 0x878f7524);
251 + current_registers.set(ustr__ZSedi(), 0x6312f9a5);
252 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
253 ASSERT_TRUE(cfi_frame_info.get());
254 ASSERT_TRUE(cfi_frame_info.get()
255 ->FindCallerRegs<uint32_t>(current_registers, memory,
256 &caller_registers));
257 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
258 expected_caller_registers, caller_registers));
260 frame.instruction = 0x3d41;
261 - current_registers[ustr__ZSesp()] = 0x10014;
262 + current_registers.set(ustr__ZSesp(), 0x10014);
263 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
264 ASSERT_TRUE(cfi_frame_info.get());
265 ASSERT_TRUE(cfi_frame_info.get()
266 ->FindCallerRegs<uint32_t>(current_registers, memory,
267 &caller_registers));
268 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
269 expected_caller_registers, caller_registers));
271 frame.instruction = 0x3d43;
272 - current_registers[ustr__ZSebp()] = 0x10014;
273 + current_registers.set(ustr__ZSebp(), 0x10014);
274 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
275 ASSERT_TRUE(cfi_frame_info.get());
276 ASSERT_TRUE(cfi_frame_info.get()
277 ->FindCallerRegs<uint32_t>(current_registers, memory,
278 &caller_registers));
279 VerifyRegisters(__FILE__, __LINE__,
280 expected_caller_registers, caller_registers);
282 frame.instruction = 0x3d54;
283 - current_registers[ustr__ZSebx()] = 0x6864f054U;
284 + current_registers.set(ustr__ZSebx(), 0x6864f054U);
285 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
286 ASSERT_TRUE(cfi_frame_info.get());
287 ASSERT_TRUE(cfi_frame_info.get()
288 ->FindCallerRegs<uint32_t>(current_registers, memory,
289 &caller_registers));
290 VerifyRegisters(__FILE__, __LINE__,
291 expected_caller_registers, caller_registers);
293 frame.instruction = 0x3d5a;
294 - current_registers[ustr__ZSesi()] = 0x6285f79aU;
295 + current_registers.set(ustr__ZSesi(), 0x6285f79aU);
296 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
297 ASSERT_TRUE(cfi_frame_info.get());
298 ASSERT_TRUE(cfi_frame_info.get()
299 ->FindCallerRegs<uint32_t>(current_registers, memory,
300 &caller_registers));
301 VerifyRegisters(__FILE__, __LINE__,
302 expected_caller_registers, caller_registers);
304 frame.instruction = 0x3d84;
305 - current_registers[ustr__ZSedi()] = 0x64061449U;
306 + current_registers.set(ustr__ZSedi(), 0x64061449U);
307 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
308 ASSERT_TRUE(cfi_frame_info.get());
309 ASSERT_TRUE(cfi_frame_info.get()
310 ->FindCallerRegs<uint32_t>(current_registers, memory,
311 &caller_registers));
312 VerifyRegisters(__FILE__, __LINE__,
313 expected_caller_registers, caller_registers);
315 diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-inl.h
316 --- a/src/processor/cfi_frame_info-inl.h
317 +++ b/src/processor/cfi_frame_info-inl.h
318 @@ -35,64 +35,64 @@
320 #ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_
321 #define PROCESSOR_CFI_FRAME_INFO_INL_H_
323 #include <string.h>
325 namespace google_breakpad {
327 -template <typename RegisterType, class RawContextType>
328 -bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters(
329 +template <typename RegisterValueType, class RawContextType>
330 +bool SimpleCFIWalker<RegisterValueType, RawContextType>::FindCallerRegisters(
331 const MemoryRegion &memory,
332 const CFIFrameInfo &cfi_frame_info,
333 const RawContextType &callee_context,
334 int callee_validity,
335 RawContextType *caller_context,
336 int *caller_validity) const {
337 - typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap;
338 + typedef CFIFrameInfo::RegisterValueMap<RegisterValueType> ValueMap;
339 ValueMap callee_registers;
340 ValueMap caller_registers;
341 - // Just for brevity.
342 - typename ValueMap::const_iterator caller_none = caller_registers.end();
344 // Populate callee_registers with register values from callee_context.
345 for (size_t i = 0; i < map_size_; i++) {
346 const RegisterSet &r = register_map_[i];
347 if (callee_validity & r.validity_flag)
348 - callee_registers[r.name] = callee_context.*r.context_member;
349 + callee_registers.set(r.name, callee_context.*r.context_member);
350 }
352 // Apply the rules, and see what register values they yield.
353 - if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory,
354 - &caller_registers))
355 + if (!cfi_frame_info
356 + .FindCallerRegs<RegisterValueType>(callee_registers, memory,
357 + &caller_registers))
358 return false;
360 // Populate *caller_context with the values the rules placed in
361 // caller_registers.
362 memset(caller_context, 0xda, sizeof(*caller_context));
363 *caller_validity = 0;
364 for (size_t i = 0; i < map_size_; i++) {
365 const RegisterSet &r = register_map_[i];
366 - typename ValueMap::const_iterator caller_entry;
368 // Did the rules provide a value for this register by its name?
369 - caller_entry = caller_registers.find(r.name);
370 - if (caller_entry != caller_none) {
371 - caller_context->*r.context_member = caller_entry->second;
372 + bool found = false;
373 + RegisterValueType v = caller_registers.get(&found, r.name);
374 + if (found) {
375 + caller_context->*r.context_member = v;
376 *caller_validity |= r.validity_flag;
377 continue;
378 }
380 // Did the rules provide a value for this register under its
381 // alternate name?
382 if (r.alternate_name) {
383 - caller_entry = caller_registers.find(r.alternate_name);
384 - if (caller_entry != caller_none) {
385 - caller_context->*r.context_member = caller_entry->second;
386 + found = false;
387 + v = caller_registers.get(&found, r.alternate_name);
388 + if (found) {
389 + caller_context->*r.context_member = v;
390 *caller_validity |= r.validity_flag;
391 continue;
392 }
393 }
395 // Is this a callee-saves register? The walker assumes that these
396 // still hold the caller's value if the CFI doesn't mention them.
397 //
398 diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
399 --- a/src/processor/cfi_frame_info.cc
400 +++ b/src/processor/cfi_frame_info.cc
401 @@ -66,33 +66,33 @@
402 V cfa;
403 working = registers;
404 if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
405 return false;
407 // Then, compute the return address.
408 V ra;
409 working = registers;
410 - working[ustr__ZDcfa()] = cfa;
411 + working.set(ustr__ZDcfa(), cfa);
412 if (!evaluator.EvaluateForValue(ra_rule_, &ra))
413 return false;
415 // Now, compute values for all the registers register_rules_ mentions.
416 for (RuleMap::const_iterator it = register_rules_.begin();
417 it != register_rules_.end(); it++) {
418 V value;
419 working = registers;
420 - working[ustr__ZDcfa()] = cfa;
421 + working.set(ustr__ZDcfa(), cfa);
422 if (!evaluator.EvaluateForValue(it->second, &value))
423 return false;
424 - (*caller_registers)[it->first] = value;
425 + caller_registers->set(it->first, value);
426 }
428 - (*caller_registers)[ustr__ZDra()] = ra;
429 - (*caller_registers)[ustr__ZDcfa()] = cfa;
430 + caller_registers->set(ustr__ZDra(), ra);
431 + caller_registers->set(ustr__ZDcfa(), cfa);
433 return true;
434 }
436 // Explicit instantiations for 32-bit and 64-bit architectures.
437 template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
438 const RegisterValueMap<uint32_t> ®isters,
439 const MemoryRegion &memory,
440 diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
441 --- a/src/processor/cfi_frame_info.h
442 +++ b/src/processor/cfi_frame_info.h
443 @@ -64,17 +64,17 @@
444 // changes given by the 'STACK CFI' records up to our instruction's
445 // address. Then, use the FindCallerRegs member function to apply the
446 // rules to the callee frame's register values, yielding the caller
447 // frame's register values.
448 class CFIFrameInfo {
449 public:
450 // A map from register names onto values.
451 template<typename ValueType> class RegisterValueMap:
452 - public map<const UniqueString*, ValueType> { };
453 + public UniqueStringMap<ValueType> { };
455 // Set the expression for computing a call frame address, return
456 // address, or register's value. At least the CFA rule and the RA
457 // rule must be set before calling FindCallerRegs.
458 void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; }
459 void SetRARule(const Module::Expr& rule) { ra_rule_ = rule; }
460 void SetRegisterRule(const UniqueString* register_name,
461 const Module::Expr& rule) {
462 diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
463 --- a/src/processor/cfi_frame_info_unittest.cc
464 +++ b/src/processor/cfi_frame_info_unittest.cc
465 @@ -111,19 +111,18 @@
467 TEST_F(Simple, SetCFAAndRARule) {
468 ExpectNoMemoryReferences();
470 cfi.SetCFARule(Module::Expr("330903416631436410"));
471 cfi.SetRARule(Module::Expr("5870666104170902211"));
472 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
473 &caller_registers));
474 - ASSERT_EQ(2U, caller_registers.size());
475 - ASSERT_EQ(330903416631436410ULL, caller_registers[ustr__ZDcfa()]);
476 - ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
477 + ASSERT_EQ(330903416631436410ULL, caller_registers.get(ustr__ZDcfa()));
478 + ASSERT_EQ(5870666104170902211ULL, caller_registers.get(ustr__ZDra()));
480 ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
481 cfi.Serialize());
482 }
484 TEST_F(Simple, SetManyRules) {
485 ExpectNoMemoryReferences();
487 @@ -136,23 +135,22 @@
488 const UniqueString* reg4 = ToUniqueString("uncopyrightables");
490 cfi.SetRegisterRule(reg1, Module::Expr(".cfa 54370437 *"));
491 cfi.SetRegisterRule(reg2, Module::Expr("24076308 .cfa +"));
492 cfi.SetRegisterRule(reg3, Module::Expr(".cfa 29801007 -"));
493 cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /"));
494 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
495 &caller_registers));
496 - ASSERT_EQ(6U, caller_registers.size());
497 - ASSERT_EQ(7664691U, caller_registers[ustr__ZDcfa()]);
498 - ASSERT_EQ(107469446U, caller_registers[ustr__ZDra()]);
499 - ASSERT_EQ(416732599139967ULL, caller_registers[reg1]);
500 - ASSERT_EQ(31740999U, caller_registers[reg2]);
501 - ASSERT_EQ(-22136316ULL, caller_registers[reg3]);
502 - ASSERT_EQ(12U, caller_registers[reg4]);
503 + ASSERT_EQ(7664691U, caller_registers.get(ustr__ZDcfa()));
504 + ASSERT_EQ(107469446U, caller_registers.get(ustr__ZDra()));
505 + ASSERT_EQ(416732599139967ULL, caller_registers.get(reg1));
506 + ASSERT_EQ(31740999U, caller_registers.get(reg2));
507 + ASSERT_EQ(-22136316ULL, caller_registers.get(reg3));
508 + ASSERT_EQ(12U, caller_registers.get(reg4));
509 ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
510 ".ra: .cfa 99804755 + "
511 "pubvexingfjordschmaltzy: .cfa 29801007 - "
512 "register1: .cfa 54370437 * "
513 "uncopyrightables: 92642917 .cfa / "
514 "vodkathumbscrewingly: 24076308 .cfa +",
515 cfi.Serialize());
516 }
517 @@ -160,19 +158,18 @@
518 TEST_F(Simple, RulesOverride) {
519 ExpectNoMemoryReferences();
521 cfi.SetCFARule(Module::Expr("330903416631436410"));
522 cfi.SetRARule(Module::Expr("5870666104170902211"));
523 cfi.SetCFARule(Module::Expr("2828089117179001"));
524 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
525 &caller_registers));
526 - ASSERT_EQ(2U, caller_registers.size());
527 - ASSERT_EQ(2828089117179001ULL, caller_registers[ustr__ZDcfa()]);
528 - ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
529 + ASSERT_EQ(2828089117179001ULL, caller_registers.get(ustr__ZDcfa()));
530 + ASSERT_EQ(5870666104170902211ULL, caller_registers.get(ustr__ZDra()));
531 ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
532 cfi.Serialize());
533 }
535 class Scope: public CFIFixture, public Test { };
537 // There should be no value for .cfa in scope when evaluating the CFA rule.
538 TEST_F(Scope, CFALacksCFA) {
539 @@ -196,37 +193,35 @@
541 // The current frame's registers should be in scope when evaluating
542 // the CFA rule.
543 TEST_F(Scope, CFASeesCurrentRegs) {
544 ExpectNoMemoryReferences();
546 const UniqueString* reg1 = ToUniqueString(".baraminology");
547 const UniqueString* reg2 = ToUniqueString(".ornithorhynchus");
548 - registers[reg1] = 0x06a7bc63e4f13893ULL;
549 - registers[reg2] = 0x5e0bf850bafce9d2ULL;
550 + registers.set(reg1, 0x06a7bc63e4f13893ULL);
551 + registers.set(reg2, 0x5e0bf850bafce9d2ULL);
552 cfi.SetCFARule(Module::Expr(".baraminology .ornithorhynchus +"));
553 cfi.SetRARule(Module::Expr("0"));
554 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
555 &caller_registers));
556 - ASSERT_EQ(2U, caller_registers.size());
557 ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
558 - caller_registers[ustr__ZDcfa()]);
559 + caller_registers.get(ustr__ZDcfa()));
560 }
562 // .cfa should be in scope in the return address expression.
563 TEST_F(Scope, RASeesCFA) {
564 ExpectNoMemoryReferences();
566 cfi.SetCFARule(Module::Expr("48364076"));
567 cfi.SetRARule(Module::Expr(".cfa"));
568 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
569 &caller_registers));
570 - ASSERT_EQ(2U, caller_registers.size());
571 - ASSERT_EQ(48364076U, caller_registers[ustr__ZDra()]);
572 + ASSERT_EQ(48364076U, caller_registers.get(ustr__ZDra()));
573 }
575 // There should be no value for .ra in scope when evaluating the CFA rule.
576 TEST_F(Scope, RALacksRA) {
577 ExpectNoMemoryReferences();
579 cfi.SetCFARule(Module::Expr("0"));
580 cfi.SetRARule(Module::Expr(".ra"));
581 @@ -236,36 +231,34 @@
583 // The current frame's registers should be in scope in the return
584 // address expression.
585 TEST_F(Scope, RASeesCurrentRegs) {
586 ExpectNoMemoryReferences();
588 cfi.SetCFARule(Module::Expr("10359370"));
589 const UniqueString* reg1 = ToUniqueString("noachian");
590 - registers[reg1] = 0x54dc4a5d8e5eb503ULL;
591 + registers.set(reg1, 0x54dc4a5d8e5eb503ULL);
592 cfi.SetRARule(Module::Expr(reg1, 0, false));
593 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
594 &caller_registers));
595 - ASSERT_EQ(2U, caller_registers.size());
596 - ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[ustr__ZDra()]);
597 + ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers.get(ustr__ZDra()));
598 }
600 // .cfa should be in scope for register rules.
601 TEST_F(Scope, RegistersSeeCFA) {
602 ExpectNoMemoryReferences();
604 cfi.SetCFARule(Module::Expr("6515179"));
605 cfi.SetRARule(Module::Expr(".cfa"));
606 const UniqueString* reg1 = ToUniqueString("rogerian");
607 cfi.SetRegisterRule(reg1, Module::Expr(".cfa"));
608 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
609 &caller_registers));
610 - ASSERT_EQ(3U, caller_registers.size());
611 - ASSERT_EQ(6515179U, caller_registers[reg1]);
612 + ASSERT_EQ(6515179U, caller_registers.get(reg1));
613 }
615 // The return address should not be in scope for register rules.
616 TEST_F(Scope, RegsLackRA) {
617 ExpectNoMemoryReferences();
619 cfi.SetCFARule(Module::Expr("42740329"));
620 cfi.SetRARule(Module::Expr("27045204"));
621 @@ -276,27 +269,26 @@
622 }
624 // Register rules can see the current frame's register values.
625 TEST_F(Scope, RegsSeeRegs) {
626 ExpectNoMemoryReferences();
628 const UniqueString* reg1 = ToUniqueString("$r1");
629 const UniqueString* reg2 = ToUniqueString("$r2");
630 - registers[reg1] = 0x6ed3582c4bedb9adULL;
631 - registers[reg2] = 0xd27d9e742b8df6d0ULL;
632 + registers.set(reg1, 0x6ed3582c4bedb9adULL);
633 + registers.set(reg2, 0xd27d9e742b8df6d0ULL);
634 cfi.SetCFARule(Module::Expr("88239303"));
635 cfi.SetRARule(Module::Expr("30503835"));
636 cfi.SetRegisterRule(reg1, Module::Expr("$r1 42175211 = $r2"));
637 cfi.SetRegisterRule(reg2, Module::Expr("$r2 21357221 = $r1"));
638 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
639 &caller_registers));
640 - ASSERT_EQ(4U, caller_registers.size());
641 - ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers[reg1]);
642 - ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers[reg2]);
643 + ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers.get(reg1));
644 + ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers.get(reg2));
645 }
647 // Each rule's temporaries are separate.
648 TEST_F(Scope, SeparateTempsRA) {
649 ExpectNoMemoryReferences();
651 cfi.SetCFARule(Module::Expr("$temp1 76569129 = $temp1"));
652 cfi.SetRARule(Module::Expr("0"));
653 @@ -440,39 +432,39 @@
654 CFIFrameInfoParseHandler handler;
655 };
657 class ParseHandler: public ParseHandlerFixture, public Test { };
659 TEST_F(ParseHandler, CFARARule) {
660 handler.CFARule("reg-for-cfa");
661 handler.RARule("reg-for-ra");
662 - registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
663 - registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
664 + registers.set(ToUniqueString("reg-for-cfa"), 0x268a9a4a3821a797ULL);
665 + registers.set(ToUniqueString("reg-for-ra"), 0x6301b475b8b91c02ULL);
666 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
667 &caller_registers));
668 - ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
669 - ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
670 + ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers.get(ustr__ZDcfa()));
671 + ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers.get(ustr__ZDra()));
672 }
674 TEST_F(ParseHandler, RegisterRules) {
675 handler.CFARule("reg-for-cfa");
676 handler.RARule("reg-for-ra");
677 handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1");
678 handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2");
679 - registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
680 - registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
681 - registers[ToUniqueString("reg-for-reg1")] = 0x06cde8e2ff062481ULL;
682 - registers[ToUniqueString("reg-for-reg2")] = 0xff0c4f76403173e2ULL;
683 + registers.set(ToUniqueString("reg-for-cfa"), 0x268a9a4a3821a797ULL);
684 + registers.set(ToUniqueString("reg-for-ra"), 0x6301b475b8b91c02ULL);
685 + registers.set(ToUniqueString("reg-for-reg1"), 0x06cde8e2ff062481ULL);
686 + registers.set(ToUniqueString("reg-for-reg2"), 0xff0c4f76403173e2ULL);
687 ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
688 &caller_registers));
689 - ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
690 - ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
691 - ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers[ToUniqueString("reg1")]);
692 - ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers[ToUniqueString("reg2")]);
693 + ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers.get(ustr__ZDcfa()));
694 + ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers.get(ustr__ZDra()));
695 + ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers.get(ToUniqueString("reg1")));
696 + ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers.get(ToUniqueString("reg2")));
697 }
699 struct SimpleCFIWalkerFixture {
700 struct RawContext {
701 uint64_t r0, r1, r2, r3, r4, sp, pc;
702 };
703 enum Validity {
704 R0_VALID = 0x01,
705 diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
706 --- a/src/processor/fast_source_line_resolver_unittest.cc
707 +++ b/src/processor/fast_source_line_resolver_unittest.cc
708 @@ -59,16 +59,17 @@
709 using google_breakpad::FromUniqueString;
710 using google_breakpad::ModuleSerializer;
711 using google_breakpad::ModuleComparer;
712 using google_breakpad::CFIFrameInfo;
713 using google_breakpad::CodeModule;
714 using google_breakpad::MemoryRegion;
715 using google_breakpad::StackFrame;
716 using google_breakpad::ToUniqueString;
717 +using google_breakpad::UniqueString;
718 using google_breakpad::WindowsFrameInfo;
719 using google_breakpad::linked_ptr;
720 using google_breakpad::scoped_ptr;
721 using google_breakpad::ustr__ZDcfa;
722 using google_breakpad::ustr__ZDra;
723 using google_breakpad::ustr__ZSebx;
724 using google_breakpad::ustr__ZSebp;
725 using google_breakpad::ustr__ZSedi;
726 @@ -125,27 +126,30 @@
727 };
729 // Verify that, for every association in ACTUAL, EXPECTED has the same
730 // association. (That is, ACTUAL's associations should be a subset of
731 // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
732 // ".cfa".
733 static bool VerifyRegisters(
734 const char *file, int line,
735 - const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
736 - const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
737 - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
738 + const std::map<const UniqueString*, uint32_t> &expected,
739 + const CFIFrameInfo::RegisterValueMap<uint32_t> &actual_regmap) {
740 + std::map<const UniqueString*, uint32_t> actual;
741 + actual_regmap.copy_to_map(&actual);
742 +
743 + std::map<const UniqueString*, uint32_t>::const_iterator a;
744 a = actual.find(ustr__ZDcfa());
745 if (a == actual.end())
746 return false;
747 a = actual.find(ustr__ZDra());
748 if (a == actual.end())
749 return false;
750 for (a = actual.begin(); a != actual.end(); a++) {
751 - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
752 + std::map<const UniqueString*, uint32_t>::const_iterator e =
753 expected.find(a->first);
754 if (e == expected.end()) {
755 fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
756 file, line, FromUniqueString(a->first), a->second);
757 return false;
758 }
759 if (e->second != a->second) {
760 fprintf(stderr,
761 @@ -286,86 +290,87 @@
763 frame.instruction = 0x3e9f;
764 frame.module = &module1;
765 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
766 ASSERT_FALSE(cfi_frame_info.get());
768 CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
769 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
770 - CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
771 + std::map<const UniqueString*, uint32_t> expected_caller_registers;
772 MockMemoryRegion memory;
774 // Regardless of which instruction evaluation takes place at, it
775 // should produce the same values for the caller's registers.
776 + // should produce the same values for the caller's registers.
777 expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
778 - expected_caller_registers[ustr__ZDra()] = 0xf6438648;
779 + expected_caller_registers[ustr__ZDra()] = 0xf6438648;
780 expected_caller_registers[ustr__ZSebp()] = 0x10038;
781 expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
782 expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
783 expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
785 frame.instruction = 0x3d40;
786 frame.module = &module1;
787 current_registers.clear();
788 - current_registers[ustr__ZSesp()] = 0x10018;
789 - current_registers[ustr__ZSebp()] = 0x10038;
790 - current_registers[ustr__ZSebx()] = 0x98ecadc3;
791 - current_registers[ustr__ZSesi()] = 0x878f7524;
792 - current_registers[ustr__ZSedi()] = 0x6312f9a5;
793 + current_registers.set(ustr__ZSesp(), 0x10018);
794 + current_registers.set(ustr__ZSebp(), 0x10038);
795 + current_registers.set(ustr__ZSebx(), 0x98ecadc3);
796 + current_registers.set(ustr__ZSesi(), 0x878f7524);
797 + current_registers.set(ustr__ZSedi(), 0x6312f9a5);
798 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
799 ASSERT_TRUE(cfi_frame_info.get());
800 ASSERT_TRUE(cfi_frame_info.get()
801 ->FindCallerRegs<uint32_t>(current_registers, memory,
802 &caller_registers));
803 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
804 expected_caller_registers, caller_registers));
806 frame.instruction = 0x3d41;
807 - current_registers[ustr__ZSesp()] = 0x10014;
808 + current_registers.set(ustr__ZSesp(), 0x10014);
809 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
810 ASSERT_TRUE(cfi_frame_info.get());
811 ASSERT_TRUE(cfi_frame_info.get()
812 ->FindCallerRegs<uint32_t>(current_registers, memory,
813 &caller_registers));
814 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
815 expected_caller_registers, caller_registers));
817 frame.instruction = 0x3d43;
818 - current_registers[ustr__ZSebp()] = 0x10014;
819 + current_registers.set(ustr__ZSebp(), 0x10014);
820 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
821 ASSERT_TRUE(cfi_frame_info.get());
822 ASSERT_TRUE(cfi_frame_info.get()
823 ->FindCallerRegs<uint32_t>(current_registers, memory,
824 &caller_registers));
825 VerifyRegisters(__FILE__, __LINE__,
826 expected_caller_registers, caller_registers);
828 frame.instruction = 0x3d54;
829 - current_registers[ustr__ZSebx()] = 0x6864f054U;
830 + current_registers.set(ustr__ZSebx(), 0x6864f054U);
831 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
832 ASSERT_TRUE(cfi_frame_info.get());
833 ASSERT_TRUE(cfi_frame_info.get()
834 ->FindCallerRegs<uint32_t>(current_registers, memory,
835 &caller_registers));
836 VerifyRegisters(__FILE__, __LINE__,
837 expected_caller_registers, caller_registers);
839 frame.instruction = 0x3d5a;
840 - current_registers[ustr__ZSesi()] = 0x6285f79aU;
841 + current_registers.set(ustr__ZSesi(), 0x6285f79aU);
842 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
843 ASSERT_TRUE(cfi_frame_info.get());
844 ASSERT_TRUE(cfi_frame_info.get()
845 ->FindCallerRegs<uint32_t>(current_registers, memory,
846 &caller_registers));
847 VerifyRegisters(__FILE__, __LINE__,
848 expected_caller_registers, caller_registers);
850 frame.instruction = 0x3d84;
851 - current_registers[ustr__ZSedi()] = 0x64061449U;
852 + current_registers.set(ustr__ZSedi(), 0x64061449U);
853 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
854 ASSERT_TRUE(cfi_frame_info.get());
855 ASSERT_TRUE(cfi_frame_info.get()
856 ->FindCallerRegs<uint32_t>(current_registers, memory,
857 &caller_registers));
858 VerifyRegisters(__FILE__, __LINE__,
859 expected_caller_registers, caller_registers);
861 diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h
862 --- a/src/processor/postfix_evaluator-inl.h
863 +++ b/src/processor/postfix_evaluator-inl.h
864 @@ -185,19 +185,19 @@
865 return false;
866 }
867 if (identifier == ustr__empty() || Index(identifier,0) != '$') {
868 BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " <<
869 identifier << ": " << expression;
870 return false;
871 }
873 - (*dictionary_)[identifier] = value;
874 + dictionary_->set(identifier, value);
875 if (assigned)
876 - (*assigned)[identifier] = true;
877 + assigned->set(identifier, true);
878 } else {
879 // Push it onto the stack as-is, but first convert it either to a
880 // ValueType (if a literal) or to a UniqueString* (if an identifier).
881 //
882 // First, try to treat the value as a literal. Literals may have leading
883 // '-' sign, and the entire remaining string must be parseable as
884 // ValueType. If this isn't possible, it can't be a literal, so treat it
885 // as an identifier instead.
886 @@ -300,28 +300,28 @@
888 return PopValue(result);
889 }
891 // Simple-form expressions
892 case Module::kExprSimple:
893 case Module::kExprSimpleMem: {
894 // Look up the base value
895 - typename DictionaryType::const_iterator iterator
896 - = dictionary_->find(expr.ident_);
897 - if (iterator == dictionary_->end()) {
898 + bool found = false;
899 + ValueType v = dictionary_->get(&found, expr.ident_);
900 + if (!found) {
901 // The identifier wasn't found in the dictionary. Don't imply any
902 // default value, just fail.
903 - BPLOG(INFO) << "Identifier " << expr.ident_
904 + BPLOG(INFO) << "Identifier " << FromUniqueString(expr.ident_)
905 << " not in dictionary (kExprSimple{Mem})";
906 return false;
907 }
909 // Form the sum
910 - ValueType sum = iterator->second + (int64_t)expr.offset_;
911 + ValueType sum = v + (int64_t)expr.offset_;
913 // and dereference if necessary
914 if (expr.how_ == Module::kExprSimpleMem) {
915 ValueType derefd;
916 if (!memory_ || !memory_->GetMemoryAtAddress(sum, &derefd)) {
917 return false;
918 }
919 *result = derefd;
920 @@ -368,27 +368,27 @@
921 if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) {
922 return false;
923 } else if (result == POP_RESULT_VALUE) {
924 // This is the easy case.
925 *value = literal;
926 } else { // result == POP_RESULT_IDENTIFIER
927 // There was an identifier at the top of the stack. Resolve it to a
928 // value by looking it up in the dictionary.
929 - typename DictionaryType::const_iterator iterator =
930 - dictionary_->find(token);
931 - if (iterator == dictionary_->end()) {
932 + bool found = false;
933 + ValueType v = dictionary_->get(&found, token);
934 + if (!found) {
935 // The identifier wasn't found in the dictionary. Don't imply any
936 // default value, just fail.
937 BPLOG(INFO) << "Identifier " << FromUniqueString(token)
938 << " not in dictionary";
939 return false;
940 }
942 - *value = iterator->second;
943 + *value = v;
944 }
946 return true;
947 }
950 template<typename ValueType>
951 bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1,
952 diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
953 --- a/src/processor/postfix_evaluator.h
954 +++ b/src/processor/postfix_evaluator.h
955 @@ -93,18 +93,18 @@
956 StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; }
957 bool isValue;
958 union { ValueType val; const UniqueString* ustr; } u;
959 };
961 template<typename ValueType>
962 class PostfixEvaluator {
963 public:
964 - typedef map<const UniqueString*, ValueType> DictionaryType;
965 - typedef map<const UniqueString*, bool> DictionaryValidityType;
966 + typedef UniqueStringMap<ValueType> DictionaryType;
967 + typedef UniqueStringMap<bool> DictionaryValidityType;
969 // Create a PostfixEvaluator object that may be used (with Evaluate) on
970 // one or more expressions. PostfixEvaluator does not take ownership of
971 // either argument. |memory| may be NULL, in which case dereferencing
972 // (^) will not be supported. |dictionary| may be NULL, but evaluation
973 // will fail in that case unless set_dictionary is used before calling
974 // Evaluate.
975 PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory)
976 diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
977 --- a/src/processor/postfix_evaluator_unittest.cc
978 +++ b/src/processor/postfix_evaluator_unittest.cc
979 @@ -178,22 +178,22 @@
980 validate_data_0[ToUniqueString("$rAdd3")] = 4;
981 validate_data_0[ToUniqueString("$rMul2")] = 54;
983 // The second test set simulates a couple of MSVC program strings.
984 // The data is fudged a little bit because the tests use FakeMemoryRegion
985 // instead of a real stack snapshot, but the program strings are real and
986 // the implementation doesn't know or care that the data is not real.
987 PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
988 - dictionary_1[ustr__ZSebp()] = 0xbfff0010;
989 - dictionary_1[ustr__ZSeip()] = 0x10000000;
990 - dictionary_1[ustr__ZSesp()] = 0xbfff0000;
991 - dictionary_1[ustr__ZDcbSavedRegs()] = 4;
992 - dictionary_1[ustr__ZDcbParams()] = 4;
993 - dictionary_1[ustr__ZDraSearchStart()] = 0xbfff0020;
994 + dictionary_1.set(ustr__ZSebp(), 0xbfff0010);
995 + dictionary_1.set(ustr__ZSeip(), 0x10000000);
996 + dictionary_1.set(ustr__ZSesp(), 0xbfff0000);
997 + dictionary_1.set(ustr__ZDcbSavedRegs(), 4);
998 + dictionary_1.set(ustr__ZDcbParams(), 4);
999 + dictionary_1.set(ustr__ZDraSearchStart(), 0xbfff0020);
1000 const EvaluateTest evaluate_tests_1[] = {
1001 { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
1002 "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
1003 // Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015,
1004 // $ebp = 0xbfff0011, $esp = 0xbfff0018,
1005 // $L = 0xbfff000c, $P = 0xbfff001c
1006 { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
1007 "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =",
1008 @@ -273,70 +273,65 @@
1009 for (map<const UniqueString*, unsigned int>::const_iterator
1010 validate_iterator =
1011 evaluate_test_set->validate_data->begin();
1012 validate_iterator != evaluate_test_set->validate_data->end();
1013 ++validate_iterator) {
1014 const UniqueString* identifier = validate_iterator->first;
1015 unsigned int expected_value = validate_iterator->second;
1017 - map<const UniqueString*, unsigned int>::const_iterator
1018 - dictionary_iterator =
1019 - evaluate_test_set->dictionary->find(identifier);
1020 -
1021 // The identifier must exist in the dictionary.
1022 - if (dictionary_iterator == evaluate_test_set->dictionary->end()) {
1023 + if (!evaluate_test_set->dictionary->have(identifier)) {
1024 fprintf(stderr, "FAIL: evaluate test set %d/%d, "
1025 "validate identifier \"%s\", "
1026 "expected %d, observed not found\n",
1027 evaluate_test_set_index, evaluate_test_set_count,
1028 FromUniqueString(identifier), expected_value);
1029 return false;
1030 }
1032 // The value in the dictionary must be the same as the expected value.
1033 - unsigned int observed_value = dictionary_iterator->second;
1034 + unsigned int observed_value =
1035 + evaluate_test_set->dictionary->get(identifier);
1036 if (expected_value != observed_value) {
1037 fprintf(stderr, "FAIL: evaluate test set %d/%d, "
1038 "validate identifier \"%s\", "
1039 "expected %d, observed %d\n",
1040 evaluate_test_set_index, evaluate_test_set_count,
1041 FromUniqueString(identifier), expected_value, observed_value);
1042 return false;
1043 }
1045 // The value must be set in the "assigned" dictionary if it was a
1046 // variable. It must not have been assigned if it was a constant.
1047 bool expected_assigned = FromUniqueString(identifier)[0] == '$';
1048 bool observed_assigned = false;
1049 - PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator
1050 - iterator_assigned = assigned.find(identifier);
1051 - if (iterator_assigned != assigned.end()) {
1052 - observed_assigned = iterator_assigned->second;
1053 + if (assigned.have(identifier)) {
1054 + observed_assigned = assigned.get(identifier);
1055 }
1056 if (expected_assigned != observed_assigned) {
1057 fprintf(stderr, "FAIL: evaluate test set %d/%d, "
1058 "validate assignment of \"%s\", "
1059 "expected %d, observed %d\n",
1060 evaluate_test_set_index, evaluate_test_set_count,
1061 FromUniqueString(identifier), expected_assigned,
1062 observed_assigned);
1063 return false;
1064 }
1065 }
1066 }
1068 // EvaluateForValue tests.
1069 PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
1070 - dictionary_2[ustr__ZSebp()] = 0xbfff0010;
1071 - dictionary_2[ustr__ZSeip()] = 0x10000000;
1072 - dictionary_2[ustr__ZSesp()] = 0xbfff0000;
1073 - dictionary_2[ustr__ZDcbSavedRegs()] = 4;
1074 - dictionary_2[ustr__ZDcbParams()] = 4;
1075 - dictionary_2[ustr__ZDraSearchStart()] = 0xbfff0020;
1076 + dictionary_2.set(ustr__ZSebp(), 0xbfff0010);
1077 + dictionary_2.set(ustr__ZSeip(), 0x10000000);
1078 + dictionary_2.set(ustr__ZSesp(), 0xbfff0000);
1079 + dictionary_2.set(ustr__ZDcbSavedRegs(), 4);
1080 + dictionary_2.set(ustr__ZDcbParams(), 4);
1081 + dictionary_2.set(ustr__ZDraSearchStart(), 0xbfff0020);
1082 const EvaluateForValueTest evaluate_for_value_tests_2[] = {
1083 { "28907223", true, 28907223 }, // simple constant
1084 { "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic
1085 { "-870245 8769343 +", true, 7899098 }, // negative constants
1086 { "$ebp $esp - $eip +", true, 0x10000010 }, // variable references
1087 { "18929794 34015074", false, 0 }, // too many values
1088 { "$ebp $ebp 4 - =", false, 0 }, // too few values
1089 { "$new $eip = $new", true, 0x10000000 }, // make new variable
1090 @@ -370,41 +365,43 @@
1091 if (test->evaluable && result != test->value) {
1092 fprintf(stderr, "FAIL: evaluate for value test %d, "
1093 "expected value to be 0x%x, but it was 0x%x\n",
1094 i, test->value, result);
1095 return false;
1096 }
1097 }
1099 + map<const UniqueString*, unsigned int> dictionary_2_map;
1100 + dictionary_2.copy_to_map(&dictionary_2_map);
1101 for (map<const UniqueString*, unsigned int>::iterator v =
1102 validate_data_2.begin();
1103 v != validate_data_2.end(); v++) {
1104 map<const UniqueString*, unsigned int>::iterator a =
1105 - dictionary_2.find(v->first);
1106 - if (a == dictionary_2.end()) {
1107 + dictionary_2_map.find(v->first);
1108 + if (a == dictionary_2_map.end()) {
1109 fprintf(stderr, "FAIL: evaluate for value dictionary check: "
1110 "expected dict[\"%s\"] to be 0x%x, but it was unset\n",
1111 FromUniqueString(v->first), v->second);
1112 return false;
1113 } else if (a->second != v->second) {
1114 fprintf(stderr, "FAIL: evaluate for value dictionary check: "
1115 "expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
1116 FromUniqueString(v->first), v->second, a->second);
1117 return false;
1118 - }
1119 - dictionary_2.erase(a);
1120 + }
1121 + dictionary_2_map.erase(a);
1122 }
1123 -
1124 +
1125 map<const UniqueString*, unsigned int>::iterator remaining =
1126 - dictionary_2.begin();
1127 - if (remaining != dictionary_2.end()) {
1128 + dictionary_2_map.begin();
1129 + if (remaining != dictionary_2_map.end()) {
1130 fprintf(stderr, "FAIL: evaluation of test expressions put unexpected "
1131 "values in dictionary:\n");
1132 - for (; remaining != dictionary_2.end(); remaining++)
1133 + for (; remaining != dictionary_2_map.end(); remaining++)
1134 fprintf(stderr, " dict[\"%s\"] == 0x%x\n",
1135 FromUniqueString(remaining->first), remaining->second);
1136 return false;
1137 }
1139 return true;
1140 }
1142 diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
1143 --- a/src/processor/stackwalker_arm.cc
1144 +++ b/src/processor/stackwalker_arm.cc
1145 @@ -97,70 +97,70 @@
1146 ToUniqueString("fps"), ToUniqueString("cpsr"),
1147 NULL
1148 };
1150 // Populate a dictionary with the valid register values in last_frame.
1151 CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
1152 for (int i = 0; register_names[i]; i++)
1153 if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
1154 - callee_registers[register_names[i]] = last_frame->context.iregs[i];
1155 + callee_registers.set(register_names[i], last_frame->context.iregs[i]);
1157 // Use the STACK CFI data to recover the caller's register values.
1158 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
1159 if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
1160 &caller_registers))
1161 return NULL;
1163 // Construct a new stack frame given the values the CFI recovered.
1164 scoped_ptr<StackFrameARM> frame(new StackFrameARM());
1165 for (int i = 0; register_names[i]; i++) {
1166 - CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
1167 - caller_registers.find(register_names[i]);
1168 - if (entry != caller_registers.end()) {
1169 + bool found = false;
1170 + uint32_t v = caller_registers.get(&found, register_names[i]);
1171 + if (found) {
1172 // We recovered the value of this register; fill the context with the
1173 // value from caller_registers.
1174 frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
1175 - frame->context.iregs[i] = entry->second;
1176 + frame->context.iregs[i] = v;
1177 } else if (4 <= i && i <= 11 && (last_frame->context_validity &
1178 StackFrameARM::RegisterValidFlag(i))) {
1179 // If the STACK CFI data doesn't mention some callee-saves register, and
1180 // it is valid in the callee, assume the callee has not yet changed it.
1181 // Registers r4 through r11 are callee-saves, according to the Procedure
1182 // Call Standard for the ARM Architecture, which the Linux ABI follows.
1183 frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
1184 frame->context.iregs[i] = last_frame->context.iregs[i];
1185 }
1186 }
1187 // If the CFI doesn't recover the PC explicitly, then use .ra.
1188 if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
1189 - CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
1190 - caller_registers.find(ustr__ZDra());
1191 - if (entry != caller_registers.end()) {
1192 + bool found = false;
1193 + uint32_t v = caller_registers.get(&found, ustr__ZDra());
1194 + if (found) {
1195 if (fp_register_ == -1) {
1196 frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
1197 - frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second;
1198 + frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = v;
1199 } else {
1200 // The CFI updated the link register and not the program counter.
1201 // Handle getting the program counter from the link register.
1202 frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
1203 frame->context_validity |= StackFrameARM::CONTEXT_VALID_LR;
1204 - frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = entry->second;
1205 + frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = v;
1206 frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
1207 last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
1208 }
1209 }
1210 }
1211 // If the CFI doesn't recover the SP explicitly, then use .cfa.
1212 if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
1213 - CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
1214 - caller_registers.find(ustr__ZDcfa());
1215 - if (entry != caller_registers.end()) {
1216 + bool found = false;
1217 + uint32_t v = caller_registers.get(&found, ustr__ZDcfa());
1218 + if (found) {
1219 frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP;
1220 - frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second;
1221 + frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = v;
1222 }
1223 }
1225 // If we didn't recover the PC and the SP, then the frame isn't very useful.
1226 static const int essentials = (StackFrameARM::CONTEXT_VALID_SP
1227 | StackFrameARM::CONTEXT_VALID_PC);
1228 if ((frame->context_validity & essentials) != essentials)
1229 return NULL;
1230 diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
1231 --- a/src/processor/stackwalker_x86.cc
1232 +++ b/src/processor/stackwalker_x86.cc
1233 @@ -194,26 +194,26 @@
1234 }
1235 }
1237 // Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used
1238 // in each program string, and their previous values are known, so set them
1239 // here.
1240 PostfixEvaluator<uint32_t>::DictionaryType dictionary;
1241 // Provide the current register values.
1242 - dictionary[ustr__ZSebp()] = last_frame->context.ebp;
1243 - dictionary[ustr__ZSesp()] = last_frame->context.esp;
1244 + dictionary.set(ustr__ZSebp(), last_frame->context.ebp);
1245 + dictionary.set(ustr__ZSesp(), last_frame->context.esp);
1246 // Provide constants from the debug info for last_frame and its callee.
1247 // .cbCalleeParams is a Breakpad extension that allows us to use the
1248 // PostfixEvaluator engine when certain types of debugging information
1249 // are present without having to write the constants into the program
1250 // string as literals.
1251 - dictionary[ustr__ZDcbCalleeParams()] = last_frame_callee_parameter_size;
1252 - dictionary[ustr__ZDcbSavedRegs()] = last_frame_info->saved_register_size;
1253 - dictionary[ustr__ZDcbLocals()] = last_frame_info->local_size;
1254 + dictionary.set(ustr__ZDcbCalleeParams(), last_frame_callee_parameter_size);
1255 + dictionary.set(ustr__ZDcbSavedRegs(), last_frame_info->saved_register_size);
1256 + dictionary.set(ustr__ZDcbLocals(), last_frame_info->local_size);
1258 uint32_t raSearchStart = last_frame->context.esp +
1259 last_frame_callee_parameter_size +
1260 last_frame_info->local_size +
1261 last_frame_info->saved_register_size;
1263 uint32_t raSearchStartOld = raSearchStart;
1264 uint32_t found = 0; // dummy value
1265 @@ -232,20 +232,20 @@
1266 // Skip one slot from the stack and do another scan in order to get the
1267 // actual return address.
1268 raSearchStart += 4;
1269 ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
1270 }
1272 // The difference between raSearch and raSearchStart is unknown,
1273 // but making them the same seems to work well in practice.
1274 - dictionary[ustr__ZDraSearchStart()] = raSearchStart;
1275 - dictionary[ustr__ZDraSearch()] = raSearchStart;
1276 + dictionary.set(ustr__ZDraSearchStart(), raSearchStart);
1277 + dictionary.set(ustr__ZDraSearch(), raSearchStart);
1279 - dictionary[ustr__ZDcbParams()] = last_frame_info->parameter_size;
1280 + dictionary.set(ustr__ZDcbParams(), last_frame_info->parameter_size);
1282 // Decide what type of program string to use. The program string is in
1283 // postfix notation and will be passed to PostfixEvaluator::Evaluate.
1284 // Given the dictionary and the program string, it is possible to compute
1285 // the return address and the values of other registers in the calling
1286 // function. Because of bugs described below, the stack may need to be
1287 // scanned for these values. The results of program string evaluation
1288 // will be used to determine whether to scan for better values.
1289 @@ -325,18 +325,18 @@
1290 }
1292 // Now crank it out, making sure that the program string set at least the
1293 // two required variables.
1294 PostfixEvaluator<uint32_t> evaluator =
1295 PostfixEvaluator<uint32_t>(&dictionary, memory_);
1296 PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity;
1297 if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
1298 - dictionary_validity.find(ustr__ZSeip()) == dictionary_validity.end() ||
1299 - dictionary_validity.find(ustr__ZSesp()) == dictionary_validity.end()) {
1300 + !dictionary_validity.have(ustr__ZSeip()) ||
1301 + !dictionary_validity.have(ustr__ZSesp())) {
1302 // Program string evaluation failed. It may be that %eip is not somewhere
1303 // with stack frame info, and %ebp is pointing to non-stack memory, so
1304 // our evaluation couldn't succeed. We'll scan the stack for a return
1305 // address. This can happen if the stack is in a module for which
1306 // we don't have symbols, and that module is compiled without a
1307 // frame pointer.
1308 uint32_t location_start = last_frame->context.esp;
1309 uint32_t location, eip;
1310 @@ -344,69 +344,70 @@
1311 // if we can't find an instruction pointer even with stack scanning,
1312 // give up.
1313 return NULL;
1314 }
1316 // This seems like a reasonable return address. Since program string
1317 // evaluation failed, use it and set %esp to the location above the
1318 // one where the return address was found.
1319 - dictionary[ustr__ZSeip()] = eip;
1320 - dictionary[ustr__ZSesp()] = location + 4;
1321 + dictionary.set(ustr__ZSeip(), eip);
1322 + dictionary.set(ustr__ZSesp(), location + 4);
1323 trust = StackFrame::FRAME_TRUST_SCAN;
1324 }
1326 // Since this stack frame did not use %ebp in a traditional way,
1327 // locating the return address isn't entirely deterministic. In that
1328 // case, the stack can be scanned to locate the return address.
1329 //
1330 // However, if program string evaluation resulted in both %eip and
1331 // %ebp values of 0, trust that the end of the stack has been
1332 // reached and don't scan for anything else.
1333 - if (dictionary[ustr__ZSeip()] != 0 || dictionary[ustr__ZSebp()] != 0) {
1334 + if (dictionary.get(ustr__ZSeip()) != 0 ||
1335 + dictionary.get(ustr__ZSebp()) != 0) {
1336 int offset = 0;
1338 // This scan can only be done if a CodeModules object is available, to
1339 // check that candidate return addresses are in fact inside a module.
1340 //
1341 // TODO(mmentovai): This ignores dynamically-generated code. One possible
1342 // solution is to check the minidump's memory map to see if the candidate
1343 // %eip value comes from a mapped executable page, although this would
1344 // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad
1345 // client doesn't currently write (it would need to call MiniDumpWriteDump
1346 // with the MiniDumpWithFullMemoryInfo type bit set). Even given this
1347 // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
1348 // an independent execute privilege on memory pages.
1350 - uint32_t eip = dictionary[ustr__ZSeip()];
1351 + uint32_t eip = dictionary.get(ustr__ZSeip());
1352 if (modules_ && !modules_->GetModuleForAddress(eip)) {
1353 // The instruction pointer at .raSearchStart was invalid, so start
1354 // looking one 32-bit word above that location.
1355 - uint32_t location_start = dictionary[ustr__ZDraSearchStart()] + 4;
1356 + uint32_t location_start = dictionary.get(ustr__ZDraSearchStart()) + 4;
1357 uint32_t location;
1358 if (ScanForReturnAddress(location_start, &location, &eip)) {
1359 // This is a better return address that what program string
1360 // evaluation found. Use it, and set %esp to the location above the
1361 // one where the return address was found.
1362 - dictionary[ustr__ZSeip()] = eip;
1363 - dictionary[ustr__ZSesp()] = location + 4;
1364 + dictionary.set(ustr__ZSeip(), eip);
1365 + dictionary.set(ustr__ZSesp(), location + 4);
1366 offset = location - location_start;
1367 trust = StackFrame::FRAME_TRUST_CFI_SCAN;
1368 }
1369 }
1371 if (recover_ebp) {
1372 // When trying to recover the previous value of the frame pointer (%ebp),
1373 // start looking at the lowest possible address in the saved-register
1374 // area, and look at the entire saved register area, increased by the
1375 // size of |offset| to account for additional data that may be on the
1376 // stack. The scan is performed from the highest possible address to
1377 // the lowest, because the expectation is that the function's prolog
1378 // would have saved %ebp early.
1379 - uint32_t ebp = dictionary[ustr__ZSebp()];
1380 + uint32_t ebp = dictionary.get(ustr__ZSebp());
1382 // When a scan for return address is used, it is possible to skip one or
1383 // more frames (when return address is not in a known module). One
1384 // indication for skipped frames is when the value of %ebp is lower than
1385 // the location of the return address on the stack
1386 bool has_skipped_frames =
1387 (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset);
1389 @@ -420,49 +421,49 @@
1390 location >= location_end;
1391 location -= 4) {
1392 if (!memory_->GetMemoryAtAddress(location, &ebp))
1393 break;
1395 if (memory_->GetMemoryAtAddress(ebp, &value)) {
1396 // The candidate value is a pointer to the same memory region
1397 // (the stack). Prefer it as a recovered %ebp result.
1398 - dictionary[ustr__ZSebp()] = ebp;
1399 + dictionary.set(ustr__ZSebp(), ebp);
1400 break;
1401 }
1402 }
1403 }
1404 }
1405 }
1407 // Create a new stack frame (ownership will be transferred to the caller)
1408 // and fill it in.
1409 StackFrameX86* frame = new StackFrameX86();
1411 frame->trust = trust;
1412 frame->context = last_frame->context;
1413 - frame->context.eip = dictionary[ustr__ZSeip()];
1414 - frame->context.esp = dictionary[ustr__ZSesp()];
1415 - frame->context.ebp = dictionary[ustr__ZSebp()];
1416 + frame->context.eip = dictionary.get(ustr__ZSeip());
1417 + frame->context.esp = dictionary.get(ustr__ZSesp());
1418 + frame->context.ebp = dictionary.get(ustr__ZSebp());
1419 frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
1420 StackFrameX86::CONTEXT_VALID_ESP |
1421 StackFrameX86::CONTEXT_VALID_EBP;
1423 // These are nonvolatile (callee-save) registers, and the program string
1424 // may have filled them in.
1425 - if (dictionary_validity.find(ustr__ZSebx()) != dictionary_validity.end()) {
1426 - frame->context.ebx = dictionary[ustr__ZSebx()];
1427 + if (dictionary_validity.have(ustr__ZSebx())) {
1428 + frame->context.ebx = dictionary.get(ustr__ZSebx());
1429 frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX;
1430 }
1431 - if (dictionary_validity.find(ustr__ZSesi()) != dictionary_validity.end()) {
1432 - frame->context.esi = dictionary[ustr__ZSesi()];
1433 + if (dictionary_validity.have(ustr__ZSesi())) {
1434 + frame->context.esi = dictionary.get(ustr__ZSesi());
1435 frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI;
1436 }
1437 - if (dictionary_validity.find(ustr__ZSedi()) != dictionary_validity.end()) {
1438 - frame->context.edi = dictionary[ustr__ZSedi()];
1439 + if (dictionary_validity.have(ustr__ZSedi())) {
1440 + frame->context.edi = dictionary.get(ustr__ZSedi());
1441 frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
1442 }
1444 return frame;
1445 }
1447 StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
1448 const vector<StackFrame*> &frames,