toolkit/crashreporter/breakpad-patches/04-uniquestringmap.patch

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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> &registers,
   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);
  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;
  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;
  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);
  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;
  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;
  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);
  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;
  1139    return true;
  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];
  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];
  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;
  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 @@
  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);
  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 @@
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  1444    return frame;
  1447  StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
  1448      const vector<StackFrame*> &frames,

mercurial