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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/breakpad-patches/04-uniquestringmap.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1448 @@
     1.4 +# HG changeset patch
     1.5 +# User Ted Mielczarek <ted.mielczarek@gmail.com>
     1.6 +# Date 1360255134 18000
     1.7 +# Node ID 294ce0d64d35a90be8ea91b719ead8b82aed29f7
     1.8 +# Parent  d7bfb673574a3afe8b4f76f42fb52e2545770dad
     1.9 +Rework PostfixEvaluator to use UniqueStringMap
    1.10 +Patch by Julian Seward <jseward@acm.org>, R=ted
    1.11 +
    1.12 +diff --git a/src/common/unique_string.h b/src/common/unique_string.h
    1.13 +--- a/src/common/unique_string.h
    1.14 ++++ b/src/common/unique_string.h
    1.15 +@@ -25,16 +25,17 @@
    1.16 + // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.17 + // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.18 + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.19 + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.20 + 
    1.21 + #ifndef COMMON_UNIQUE_STRING_H_
    1.22 + #define COMMON_UNIQUE_STRING_H_
    1.23 + 
    1.24 ++#include <map>
    1.25 + #include <string>
    1.26 + #include "common/using_std_string.h"
    1.27 + 
    1.28 + namespace google_breakpad {
    1.29 + 
    1.30 + // Abstract type
    1.31 + class UniqueString;
    1.32 + 
    1.33 +@@ -229,11 +230,112 @@
    1.34 + 
    1.35 + // ".ra"
    1.36 + inline static const UniqueString* ustr__ZDra() {
    1.37 +   static const UniqueString* us = NULL;
    1.38 +   if (!us) us = ToUniqueString(".ra");
    1.39 +   return us;
    1.40 + }
    1.41 + 
    1.42 ++template <typename ValueType>
    1.43 ++class UniqueStringMap
    1.44 ++{
    1.45 ++ private:
    1.46 ++  static const int N_FIXED = 10;
    1.47 ++
    1.48 ++ public:
    1.49 ++  UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {};
    1.50 ++  ~UniqueStringMap() {};
    1.51 ++
    1.52 ++  // Empty out the map.
    1.53 ++  void clear() {
    1.54 ++    ++n_clears_;
    1.55 ++    map_.clear();
    1.56 ++    n_fixed_ = 0;
    1.57 ++  }
    1.58 ++
    1.59 ++  // Do "map[ix] = v".
    1.60 ++  void set(const UniqueString* ix, ValueType v) {
    1.61 ++    ++n_sets_;
    1.62 ++    int i;
    1.63 ++    for (i = 0; i < n_fixed_; ++i) {
    1.64 ++      if (fixed_keys_[i] == ix) {
    1.65 ++        fixed_vals_[i] = v;
    1.66 ++        return;
    1.67 ++      }
    1.68 ++    }
    1.69 ++    if (n_fixed_ < N_FIXED) {
    1.70 ++      i = n_fixed_;
    1.71 ++      fixed_keys_[i] = ix;
    1.72 ++      fixed_vals_[i] = v;
    1.73 ++      ++n_fixed_;
    1.74 ++    } else {
    1.75 ++      map_[ix] = v;
    1.76 ++    }
    1.77 ++  }
    1.78 ++
    1.79 ++  // Lookup 'ix' in the map, and also return a success/fail boolean.
    1.80 ++  ValueType get(/*OUT*/bool* have, const UniqueString* ix) const {
    1.81 ++    ++n_gets_;
    1.82 ++    int i;
    1.83 ++    for (i = 0; i < n_fixed_; ++i) {
    1.84 ++      if (fixed_keys_[i] == ix) {
    1.85 ++        *have = true;
    1.86 ++        return fixed_vals_[i];
    1.87 ++      }
    1.88 ++    }
    1.89 ++    typename std::map<const UniqueString*, ValueType>::const_iterator it
    1.90 ++        = map_.find(ix);
    1.91 ++    if (it == map_.end()) {
    1.92 ++      *have = false;
    1.93 ++      return ValueType();
    1.94 ++    } else {
    1.95 ++      *have = true;
    1.96 ++      return it->second;
    1.97 ++    }
    1.98 ++  };
    1.99 ++
   1.100 ++  // Lookup 'ix' in the map, and return zero if it is not present.
   1.101 ++  ValueType get(const UniqueString* ix) const {
   1.102 ++    ++n_gets_;
   1.103 ++    bool found;
   1.104 ++    ValueType v = get(&found, ix);
   1.105 ++    return found ? v : ValueType();
   1.106 ++  }
   1.107 ++
   1.108 ++  // Find out whether 'ix' is in the map.
   1.109 ++  bool have(const UniqueString* ix) const {
   1.110 ++    ++n_gets_;
   1.111 ++    bool found;
   1.112 ++    (void)get(&found, ix);
   1.113 ++    return found;
   1.114 ++  }
   1.115 ++
   1.116 ++  // Copy the contents to a std::map, generally for testing.
   1.117 ++  void copy_to_map(std::map<const UniqueString*, ValueType>* m) const {
   1.118 ++    m->clear();
   1.119 ++    int i;
   1.120 ++    for (i = 0; i < n_fixed_; ++i) {
   1.121 ++      (*m)[fixed_keys_[i]] = fixed_vals_[i];
   1.122 ++    }
   1.123 ++    m->insert(map_.begin(), map_.end());
   1.124 ++  }
   1.125 ++
   1.126 ++  // Note that users of this class rely on having also a sane
   1.127 ++  // assignment operator.  The default one is OK, though.
   1.128 ++  // AFAICT there are no uses of the copy constructor, but if
   1.129 ++  // there were, the default one would also suffice.
   1.130 ++
   1.131 ++ private:
   1.132 ++  // Quick (hopefully) cache
   1.133 ++  const UniqueString* fixed_keys_[N_FIXED];
   1.134 ++  ValueType           fixed_vals_[N_FIXED];
   1.135 ++  int                 n_fixed_;  // 0 .. N_FIXED inclusive
   1.136 ++  // Fallback storage when the cache is filled
   1.137 ++  std::map<const UniqueString*, ValueType> map_;
   1.138 ++
   1.139 ++  // For tracking usage stats.
   1.140 ++  mutable int n_sets_, n_gets_, n_clears_;
   1.141 ++};
   1.142 ++
   1.143 + }  // namespace google_breakpad
   1.144 + 
   1.145 + #endif  // COMMON_UNIQUE_STRING_H_
   1.146 +diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
   1.147 +--- a/src/processor/basic_source_line_resolver_unittest.cc
   1.148 ++++ b/src/processor/basic_source_line_resolver_unittest.cc
   1.149 +@@ -24,16 +24,17 @@
   1.150 + // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   1.151 + // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   1.152 + // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   1.153 + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   1.154 + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1.155 + 
   1.156 + #include <stdio.h>
   1.157 + 
   1.158 ++#include <map>
   1.159 + #include <string>
   1.160 + 
   1.161 + #include "breakpad_googletest_includes.h"
   1.162 + #include "common/scoped_ptr.h"
   1.163 + #include "common/using_std_string.h"
   1.164 + #include "google_breakpad/processor/basic_source_line_resolver.h"
   1.165 + #include "google_breakpad/processor/code_module.h"
   1.166 + #include "google_breakpad/processor/stack_frame.h"
   1.167 +@@ -47,16 +48,17 @@
   1.168 + 
   1.169 + using google_breakpad::BasicSourceLineResolver;
   1.170 + using google_breakpad::CFIFrameInfo;
   1.171 + using google_breakpad::CodeModule;
   1.172 + using google_breakpad::FromUniqueString;
   1.173 + using google_breakpad::MemoryRegion;
   1.174 + using google_breakpad::StackFrame;
   1.175 + using google_breakpad::ToUniqueString;
   1.176 ++using google_breakpad::UniqueString;
   1.177 + using google_breakpad::WindowsFrameInfo;
   1.178 + using google_breakpad::linked_ptr;
   1.179 + using google_breakpad::scoped_ptr;
   1.180 + using google_breakpad::ustr__ZDcfa;
   1.181 + using google_breakpad::ustr__ZDra;
   1.182 + using google_breakpad::ustr__ZSebx;
   1.183 + using google_breakpad::ustr__ZSebp;
   1.184 + using google_breakpad::ustr__ZSedi;
   1.185 +@@ -113,27 +115,30 @@
   1.186 + };
   1.187 + 
   1.188 + // Verify that, for every association in ACTUAL, EXPECTED has the same
   1.189 + // association. (That is, ACTUAL's associations should be a subset of
   1.190 + // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
   1.191 + // ".cfa".
   1.192 + static bool VerifyRegisters(
   1.193 +     const char *file, int line,
   1.194 +-    const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
   1.195 +-    const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
   1.196 +-  CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
   1.197 ++    const std::map<const UniqueString*, uint32_t> &expected,
   1.198 ++    const CFIFrameInfo::RegisterValueMap<uint32_t> &actual_regmap) {
   1.199 ++  std::map<const UniqueString*, uint32_t> actual;
   1.200 ++  actual_regmap.copy_to_map(&actual);
   1.201 ++
   1.202 ++  std::map<const UniqueString*, uint32_t>::const_iterator a;
   1.203 +   a = actual.find(ustr__ZDcfa());
   1.204 +   if (a == actual.end())
   1.205 +     return false;
   1.206 +   a = actual.find(ustr__ZDra());
   1.207 +   if (a == actual.end())
   1.208 +     return false;
   1.209 +   for (a = actual.begin(); a != actual.end(); a++) {
   1.210 +-    CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
   1.211 ++    std::map<const UniqueString*, uint32_t>::const_iterator e =
   1.212 +       expected.find(a->first);
   1.213 +     if (e == expected.end()) {
   1.214 +       fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
   1.215 +               file, line, FromUniqueString(a->first), a->second);
   1.216 +       return false;
   1.217 +     }
   1.218 +     if (e->second != a->second) {
   1.219 +       fprintf(stderr,
   1.220 +@@ -258,86 +263,86 @@
   1.221 + 
   1.222 +   frame.instruction = 0x3e9f;
   1.223 +   frame.module = &module1;
   1.224 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.225 +   ASSERT_FALSE(cfi_frame_info.get());
   1.226 + 
   1.227 +   CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
   1.228 +   CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
   1.229 +-  CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
   1.230 ++  std::map<const UniqueString*, uint32_t> expected_caller_registers;
   1.231 +   MockMemoryRegion memory;
   1.232 + 
   1.233 +   // Regardless of which instruction evaluation takes place at, it
   1.234 +   // should produce the same values for the caller's registers.
   1.235 +   expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
   1.236 +   expected_caller_registers[ustr__ZDra()]  = 0xf6438648;
   1.237 +   expected_caller_registers[ustr__ZSebp()] = 0x10038;
   1.238 +   expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
   1.239 +   expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
   1.240 +   expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
   1.241 + 
   1.242 +   frame.instruction = 0x3d40;
   1.243 +   frame.module = &module1;
   1.244 +   current_registers.clear();
   1.245 +-  current_registers[ustr__ZSesp()] = 0x10018;
   1.246 +-  current_registers[ustr__ZSebp()] = 0x10038;
   1.247 +-  current_registers[ustr__ZSebx()] = 0x98ecadc3;
   1.248 +-  current_registers[ustr__ZSesi()] = 0x878f7524;
   1.249 +-  current_registers[ustr__ZSedi()] = 0x6312f9a5;
   1.250 ++  current_registers.set(ustr__ZSesp(), 0x10018);
   1.251 ++  current_registers.set(ustr__ZSebp(), 0x10038);
   1.252 ++  current_registers.set(ustr__ZSebx(), 0x98ecadc3);
   1.253 ++  current_registers.set(ustr__ZSesi(), 0x878f7524);
   1.254 ++  current_registers.set(ustr__ZSedi(), 0x6312f9a5);
   1.255 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.256 +   ASSERT_TRUE(cfi_frame_info.get());
   1.257 +   ASSERT_TRUE(cfi_frame_info.get()
   1.258 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.259 +                                           &caller_registers));
   1.260 +   ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
   1.261 +                               expected_caller_registers, caller_registers));
   1.262 + 
   1.263 +   frame.instruction = 0x3d41;
   1.264 +-  current_registers[ustr__ZSesp()] = 0x10014;
   1.265 ++  current_registers.set(ustr__ZSesp(), 0x10014);
   1.266 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.267 +   ASSERT_TRUE(cfi_frame_info.get());
   1.268 +   ASSERT_TRUE(cfi_frame_info.get()
   1.269 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.270 +                                           &caller_registers));
   1.271 +   ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
   1.272 +                               expected_caller_registers, caller_registers));
   1.273 + 
   1.274 +   frame.instruction = 0x3d43;
   1.275 +-  current_registers[ustr__ZSebp()] = 0x10014;
   1.276 ++  current_registers.set(ustr__ZSebp(), 0x10014);
   1.277 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.278 +   ASSERT_TRUE(cfi_frame_info.get());
   1.279 +   ASSERT_TRUE(cfi_frame_info.get()
   1.280 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.281 +                                           &caller_registers));
   1.282 +   VerifyRegisters(__FILE__, __LINE__,
   1.283 +                   expected_caller_registers, caller_registers);
   1.284 + 
   1.285 +   frame.instruction = 0x3d54;
   1.286 +-  current_registers[ustr__ZSebx()] = 0x6864f054U;
   1.287 ++  current_registers.set(ustr__ZSebx(), 0x6864f054U);
   1.288 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.289 +   ASSERT_TRUE(cfi_frame_info.get());
   1.290 +   ASSERT_TRUE(cfi_frame_info.get()
   1.291 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.292 +                                           &caller_registers));
   1.293 +   VerifyRegisters(__FILE__, __LINE__,
   1.294 +                   expected_caller_registers, caller_registers);
   1.295 + 
   1.296 +   frame.instruction = 0x3d5a;
   1.297 +-  current_registers[ustr__ZSesi()] = 0x6285f79aU;
   1.298 ++  current_registers.set(ustr__ZSesi(), 0x6285f79aU);
   1.299 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.300 +   ASSERT_TRUE(cfi_frame_info.get());
   1.301 +   ASSERT_TRUE(cfi_frame_info.get()
   1.302 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.303 +                                           &caller_registers));
   1.304 +   VerifyRegisters(__FILE__, __LINE__,
   1.305 +                   expected_caller_registers, caller_registers);
   1.306 + 
   1.307 +   frame.instruction = 0x3d84;
   1.308 +-  current_registers[ustr__ZSedi()] = 0x64061449U;
   1.309 ++  current_registers.set(ustr__ZSedi(), 0x64061449U);
   1.310 +   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
   1.311 +   ASSERT_TRUE(cfi_frame_info.get());
   1.312 +   ASSERT_TRUE(cfi_frame_info.get()
   1.313 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.314 +                                           &caller_registers));
   1.315 +   VerifyRegisters(__FILE__, __LINE__,
   1.316 +                   expected_caller_registers, caller_registers);
   1.317 + 
   1.318 +diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-inl.h
   1.319 +--- a/src/processor/cfi_frame_info-inl.h
   1.320 ++++ b/src/processor/cfi_frame_info-inl.h
   1.321 +@@ -35,64 +35,64 @@
   1.322 + 
   1.323 + #ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_
   1.324 + #define PROCESSOR_CFI_FRAME_INFO_INL_H_
   1.325 + 
   1.326 + #include <string.h>
   1.327 + 
   1.328 + namespace google_breakpad {
   1.329 + 
   1.330 +-template <typename RegisterType, class RawContextType>
   1.331 +-bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters(
   1.332 ++template <typename RegisterValueType, class RawContextType>
   1.333 ++bool SimpleCFIWalker<RegisterValueType, RawContextType>::FindCallerRegisters(
   1.334 +     const MemoryRegion &memory,
   1.335 +     const CFIFrameInfo &cfi_frame_info,
   1.336 +     const RawContextType &callee_context,
   1.337 +     int callee_validity,
   1.338 +     RawContextType *caller_context,
   1.339 +     int *caller_validity) const {
   1.340 +-  typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap;
   1.341 ++  typedef CFIFrameInfo::RegisterValueMap<RegisterValueType> ValueMap;
   1.342 +   ValueMap callee_registers;
   1.343 +   ValueMap caller_registers;
   1.344 +-  // Just for brevity.
   1.345 +-  typename ValueMap::const_iterator caller_none = caller_registers.end();
   1.346 + 
   1.347 +   // Populate callee_registers with register values from callee_context.
   1.348 +   for (size_t i = 0; i < map_size_; i++) {
   1.349 +     const RegisterSet &r = register_map_[i];
   1.350 +     if (callee_validity & r.validity_flag)
   1.351 +-      callee_registers[r.name] = callee_context.*r.context_member;
   1.352 ++      callee_registers.set(r.name, callee_context.*r.context_member);
   1.353 +   }
   1.354 + 
   1.355 +   // Apply the rules, and see what register values they yield.
   1.356 +-  if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory,
   1.357 +-                                                   &caller_registers))
   1.358 ++  if (!cfi_frame_info
   1.359 ++       .FindCallerRegs<RegisterValueType>(callee_registers, memory,
   1.360 ++                                          &caller_registers))
   1.361 +     return false;
   1.362 + 
   1.363 +   // Populate *caller_context with the values the rules placed in
   1.364 +   // caller_registers.
   1.365 +   memset(caller_context, 0xda, sizeof(*caller_context));
   1.366 +   *caller_validity = 0;
   1.367 +   for (size_t i = 0; i < map_size_; i++) {
   1.368 +     const RegisterSet &r = register_map_[i];
   1.369 +-    typename ValueMap::const_iterator caller_entry;
   1.370 + 
   1.371 +     // Did the rules provide a value for this register by its name?
   1.372 +-    caller_entry = caller_registers.find(r.name);
   1.373 +-    if (caller_entry != caller_none) {
   1.374 +-      caller_context->*r.context_member = caller_entry->second;
   1.375 ++    bool found = false;
   1.376 ++    RegisterValueType v = caller_registers.get(&found, r.name);
   1.377 ++    if (found) {
   1.378 ++      caller_context->*r.context_member = v;
   1.379 +       *caller_validity |= r.validity_flag;
   1.380 +       continue;
   1.381 +     }
   1.382 + 
   1.383 +     // Did the rules provide a value for this register under its
   1.384 +     // alternate name?
   1.385 +     if (r.alternate_name) {
   1.386 +-      caller_entry = caller_registers.find(r.alternate_name);
   1.387 +-      if (caller_entry != caller_none) {
   1.388 +-        caller_context->*r.context_member = caller_entry->second;
   1.389 ++      found = false;
   1.390 ++      v = caller_registers.get(&found, r.alternate_name);
   1.391 ++      if (found) {
   1.392 ++        caller_context->*r.context_member = v;
   1.393 +         *caller_validity |= r.validity_flag;
   1.394 +         continue;
   1.395 +       }
   1.396 +     }
   1.397 + 
   1.398 +     // Is this a callee-saves register? The walker assumes that these
   1.399 +     // still hold the caller's value if the CFI doesn't mention them.
   1.400 +     //
   1.401 +diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
   1.402 +--- a/src/processor/cfi_frame_info.cc
   1.403 ++++ b/src/processor/cfi_frame_info.cc
   1.404 +@@ -66,33 +66,33 @@
   1.405 +   V cfa;
   1.406 +   working = registers;
   1.407 +   if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
   1.408 +     return false;
   1.409 + 
   1.410 +   // Then, compute the return address.
   1.411 +   V ra;
   1.412 +   working = registers;
   1.413 +-  working[ustr__ZDcfa()] = cfa;
   1.414 ++  working.set(ustr__ZDcfa(), cfa);
   1.415 +   if (!evaluator.EvaluateForValue(ra_rule_, &ra))
   1.416 +     return false;
   1.417 + 
   1.418 +   // Now, compute values for all the registers register_rules_ mentions.
   1.419 +   for (RuleMap::const_iterator it = register_rules_.begin();
   1.420 +        it != register_rules_.end(); it++) {
   1.421 +     V value;
   1.422 +     working = registers;
   1.423 +-    working[ustr__ZDcfa()] = cfa;
   1.424 ++    working.set(ustr__ZDcfa(), cfa);
   1.425 +     if (!evaluator.EvaluateForValue(it->second, &value))
   1.426 +       return false;
   1.427 +-    (*caller_registers)[it->first] = value;
   1.428 ++    caller_registers->set(it->first, value);
   1.429 +   }
   1.430 + 
   1.431 +-  (*caller_registers)[ustr__ZDra()] = ra;
   1.432 +-  (*caller_registers)[ustr__ZDcfa()] = cfa;
   1.433 ++  caller_registers->set(ustr__ZDra(), ra);
   1.434 ++  caller_registers->set(ustr__ZDcfa(), cfa);
   1.435 + 
   1.436 +   return true;
   1.437 + }
   1.438 + 
   1.439 + // Explicit instantiations for 32-bit and 64-bit architectures.
   1.440 + template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
   1.441 +     const RegisterValueMap<uint32_t> &registers,
   1.442 +     const MemoryRegion &memory,
   1.443 +diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
   1.444 +--- a/src/processor/cfi_frame_info.h
   1.445 ++++ b/src/processor/cfi_frame_info.h
   1.446 +@@ -64,17 +64,17 @@
   1.447 + // changes given by the 'STACK CFI' records up to our instruction's
   1.448 + // address. Then, use the FindCallerRegs member function to apply the
   1.449 + // rules to the callee frame's register values, yielding the caller
   1.450 + // frame's register values.
   1.451 + class CFIFrameInfo {
   1.452 +  public:
   1.453 +   // A map from register names onto values.
   1.454 +   template<typename ValueType> class RegisterValueMap:
   1.455 +-    public map<const UniqueString*, ValueType> { };
   1.456 ++    public UniqueStringMap<ValueType> { };
   1.457 + 
   1.458 +   // Set the expression for computing a call frame address, return
   1.459 +   // address, or register's value. At least the CFA rule and the RA
   1.460 +   // rule must be set before calling FindCallerRegs.
   1.461 +   void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; }
   1.462 +   void SetRARule(const Module::Expr& rule)  { ra_rule_ = rule; }
   1.463 +   void SetRegisterRule(const UniqueString* register_name,
   1.464 +                        const Module::Expr& rule) {
   1.465 +diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
   1.466 +--- a/src/processor/cfi_frame_info_unittest.cc
   1.467 ++++ b/src/processor/cfi_frame_info_unittest.cc
   1.468 +@@ -111,19 +111,18 @@
   1.469 + 
   1.470 + TEST_F(Simple, SetCFAAndRARule) {
   1.471 +   ExpectNoMemoryReferences();
   1.472 + 
   1.473 +   cfi.SetCFARule(Module::Expr("330903416631436410"));
   1.474 +   cfi.SetRARule(Module::Expr("5870666104170902211"));
   1.475 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.476 +                                             &caller_registers));
   1.477 +-  ASSERT_EQ(2U, caller_registers.size());
   1.478 +-  ASSERT_EQ(330903416631436410ULL, caller_registers[ustr__ZDcfa()]);
   1.479 +-  ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
   1.480 ++  ASSERT_EQ(330903416631436410ULL, caller_registers.get(ustr__ZDcfa()));
   1.481 ++  ASSERT_EQ(5870666104170902211ULL, caller_registers.get(ustr__ZDra()));
   1.482 + 
   1.483 +   ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
   1.484 +             cfi.Serialize());
   1.485 + }
   1.486 + 
   1.487 + TEST_F(Simple, SetManyRules) {
   1.488 +   ExpectNoMemoryReferences();
   1.489 + 
   1.490 +@@ -136,23 +135,22 @@
   1.491 +   const UniqueString* reg4 = ToUniqueString("uncopyrightables");
   1.492 + 
   1.493 +   cfi.SetRegisterRule(reg1, Module::Expr(".cfa 54370437 *"));
   1.494 +   cfi.SetRegisterRule(reg2, Module::Expr("24076308 .cfa +"));
   1.495 +   cfi.SetRegisterRule(reg3, Module::Expr(".cfa 29801007 -"));
   1.496 +   cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /"));
   1.497 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.498 +                                             &caller_registers));
   1.499 +-  ASSERT_EQ(6U, caller_registers.size());
   1.500 +-  ASSERT_EQ(7664691U,           caller_registers[ustr__ZDcfa()]);
   1.501 +-  ASSERT_EQ(107469446U,         caller_registers[ustr__ZDra()]);
   1.502 +-  ASSERT_EQ(416732599139967ULL, caller_registers[reg1]);
   1.503 +-  ASSERT_EQ(31740999U,          caller_registers[reg2]);
   1.504 +-  ASSERT_EQ(-22136316ULL,       caller_registers[reg3]);
   1.505 +-  ASSERT_EQ(12U,                caller_registers[reg4]);
   1.506 ++  ASSERT_EQ(7664691U,           caller_registers.get(ustr__ZDcfa()));
   1.507 ++  ASSERT_EQ(107469446U,         caller_registers.get(ustr__ZDra()));
   1.508 ++  ASSERT_EQ(416732599139967ULL, caller_registers.get(reg1));
   1.509 ++  ASSERT_EQ(31740999U,          caller_registers.get(reg2));
   1.510 ++  ASSERT_EQ(-22136316ULL,       caller_registers.get(reg3));
   1.511 ++  ASSERT_EQ(12U,                caller_registers.get(reg4));
   1.512 +   ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
   1.513 +             ".ra: .cfa 99804755 + "
   1.514 +             "pubvexingfjordschmaltzy: .cfa 29801007 - "
   1.515 +             "register1: .cfa 54370437 * "
   1.516 +             "uncopyrightables: 92642917 .cfa / "
   1.517 +             "vodkathumbscrewingly: 24076308 .cfa +",
   1.518 +             cfi.Serialize());
   1.519 + }
   1.520 +@@ -160,19 +158,18 @@
   1.521 + TEST_F(Simple, RulesOverride) {
   1.522 +   ExpectNoMemoryReferences();
   1.523 + 
   1.524 +   cfi.SetCFARule(Module::Expr("330903416631436410"));
   1.525 +   cfi.SetRARule(Module::Expr("5870666104170902211"));
   1.526 +   cfi.SetCFARule(Module::Expr("2828089117179001"));
   1.527 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.528 +                                             &caller_registers));
   1.529 +-  ASSERT_EQ(2U, caller_registers.size());
   1.530 +-  ASSERT_EQ(2828089117179001ULL, caller_registers[ustr__ZDcfa()]);
   1.531 +-  ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
   1.532 ++  ASSERT_EQ(2828089117179001ULL, caller_registers.get(ustr__ZDcfa()));
   1.533 ++  ASSERT_EQ(5870666104170902211ULL, caller_registers.get(ustr__ZDra()));
   1.534 +   ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
   1.535 +             cfi.Serialize());
   1.536 + }
   1.537 + 
   1.538 + class Scope: public CFIFixture, public Test { };
   1.539 + 
   1.540 + // There should be no value for .cfa in scope when evaluating the CFA rule.
   1.541 + TEST_F(Scope, CFALacksCFA) {
   1.542 +@@ -196,37 +193,35 @@
   1.543 + 
   1.544 + // The current frame's registers should be in scope when evaluating
   1.545 + // the CFA rule.
   1.546 + TEST_F(Scope, CFASeesCurrentRegs) {
   1.547 +   ExpectNoMemoryReferences();
   1.548 + 
   1.549 +   const UniqueString* reg1 = ToUniqueString(".baraminology");
   1.550 +   const UniqueString* reg2 = ToUniqueString(".ornithorhynchus");
   1.551 +-  registers[reg1] = 0x06a7bc63e4f13893ULL;
   1.552 +-  registers[reg2] = 0x5e0bf850bafce9d2ULL;
   1.553 ++  registers.set(reg1, 0x06a7bc63e4f13893ULL);
   1.554 ++  registers.set(reg2, 0x5e0bf850bafce9d2ULL);
   1.555 +   cfi.SetCFARule(Module::Expr(".baraminology .ornithorhynchus +"));
   1.556 +   cfi.SetRARule(Module::Expr("0"));
   1.557 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.558 +                                             &caller_registers));
   1.559 +-  ASSERT_EQ(2U, caller_registers.size());
   1.560 +   ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
   1.561 +-            caller_registers[ustr__ZDcfa()]);
   1.562 ++            caller_registers.get(ustr__ZDcfa()));
   1.563 + }
   1.564 + 
   1.565 + // .cfa should be in scope in the return address expression.
   1.566 + TEST_F(Scope, RASeesCFA) {
   1.567 +   ExpectNoMemoryReferences();
   1.568 + 
   1.569 +   cfi.SetCFARule(Module::Expr("48364076"));
   1.570 +   cfi.SetRARule(Module::Expr(".cfa"));
   1.571 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.572 +                                             &caller_registers));
   1.573 +-  ASSERT_EQ(2U, caller_registers.size());
   1.574 +-  ASSERT_EQ(48364076U, caller_registers[ustr__ZDra()]);
   1.575 ++  ASSERT_EQ(48364076U, caller_registers.get(ustr__ZDra()));
   1.576 + }
   1.577 + 
   1.578 + // There should be no value for .ra in scope when evaluating the CFA rule.
   1.579 + TEST_F(Scope, RALacksRA) {
   1.580 +   ExpectNoMemoryReferences();
   1.581 + 
   1.582 +   cfi.SetCFARule(Module::Expr("0"));
   1.583 +   cfi.SetRARule(Module::Expr(".ra"));
   1.584 +@@ -236,36 +231,34 @@
   1.585 + 
   1.586 + // The current frame's registers should be in scope in the return
   1.587 + // address expression.
   1.588 + TEST_F(Scope, RASeesCurrentRegs) {
   1.589 +   ExpectNoMemoryReferences();
   1.590 + 
   1.591 +   cfi.SetCFARule(Module::Expr("10359370"));
   1.592 +   const UniqueString* reg1 = ToUniqueString("noachian");
   1.593 +-  registers[reg1] = 0x54dc4a5d8e5eb503ULL;
   1.594 ++  registers.set(reg1, 0x54dc4a5d8e5eb503ULL);
   1.595 +   cfi.SetRARule(Module::Expr(reg1, 0, false));
   1.596 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.597 +                                             &caller_registers));
   1.598 +-  ASSERT_EQ(2U, caller_registers.size());
   1.599 +-  ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[ustr__ZDra()]);
   1.600 ++  ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers.get(ustr__ZDra()));
   1.601 + }
   1.602 + 
   1.603 + // .cfa should be in scope for register rules.
   1.604 + TEST_F(Scope, RegistersSeeCFA) {
   1.605 +   ExpectNoMemoryReferences();
   1.606 + 
   1.607 +   cfi.SetCFARule(Module::Expr("6515179"));
   1.608 +   cfi.SetRARule(Module::Expr(".cfa"));
   1.609 +   const UniqueString* reg1 = ToUniqueString("rogerian");
   1.610 +   cfi.SetRegisterRule(reg1, Module::Expr(".cfa"));
   1.611 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.612 +                                             &caller_registers));
   1.613 +-  ASSERT_EQ(3U, caller_registers.size());
   1.614 +-  ASSERT_EQ(6515179U, caller_registers[reg1]);
   1.615 ++  ASSERT_EQ(6515179U, caller_registers.get(reg1));
   1.616 + }
   1.617 + 
   1.618 + // The return address should not be in scope for register rules.
   1.619 + TEST_F(Scope, RegsLackRA) {
   1.620 +   ExpectNoMemoryReferences();
   1.621 + 
   1.622 +   cfi.SetCFARule(Module::Expr("42740329"));
   1.623 +   cfi.SetRARule(Module::Expr("27045204"));
   1.624 +@@ -276,27 +269,26 @@
   1.625 + }
   1.626 + 
   1.627 + // Register rules can see the current frame's register values.
   1.628 + TEST_F(Scope, RegsSeeRegs) {
   1.629 +   ExpectNoMemoryReferences();
   1.630 + 
   1.631 +   const UniqueString* reg1 = ToUniqueString("$r1");
   1.632 +   const UniqueString* reg2 = ToUniqueString("$r2");
   1.633 +-  registers[reg1] = 0x6ed3582c4bedb9adULL;
   1.634 +-  registers[reg2] = 0xd27d9e742b8df6d0ULL;
   1.635 ++  registers.set(reg1, 0x6ed3582c4bedb9adULL);
   1.636 ++  registers.set(reg2, 0xd27d9e742b8df6d0ULL);
   1.637 +   cfi.SetCFARule(Module::Expr("88239303"));
   1.638 +   cfi.SetRARule(Module::Expr("30503835"));
   1.639 +   cfi.SetRegisterRule(reg1, Module::Expr("$r1 42175211 = $r2"));
   1.640 +   cfi.SetRegisterRule(reg2, Module::Expr("$r2 21357221 = $r1"));
   1.641 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.642 +                                             &caller_registers));
   1.643 +-  ASSERT_EQ(4U, caller_registers.size());
   1.644 +-  ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers[reg1]);
   1.645 +-  ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers[reg2]);
   1.646 ++  ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers.get(reg1));
   1.647 ++  ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers.get(reg2));
   1.648 + }
   1.649 + 
   1.650 + // Each rule's temporaries are separate.
   1.651 + TEST_F(Scope, SeparateTempsRA) {
   1.652 +   ExpectNoMemoryReferences();
   1.653 + 
   1.654 +   cfi.SetCFARule(Module::Expr("$temp1 76569129 = $temp1"));
   1.655 +   cfi.SetRARule(Module::Expr("0"));
   1.656 +@@ -440,39 +432,39 @@
   1.657 +   CFIFrameInfoParseHandler handler;
   1.658 + };
   1.659 + 
   1.660 + class ParseHandler: public ParseHandlerFixture, public Test { };
   1.661 + 
   1.662 + TEST_F(ParseHandler, CFARARule) {
   1.663 +   handler.CFARule("reg-for-cfa");
   1.664 +   handler.RARule("reg-for-ra");
   1.665 +-  registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
   1.666 +-  registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
   1.667 ++  registers.set(ToUniqueString("reg-for-cfa"), 0x268a9a4a3821a797ULL);
   1.668 ++  registers.set(ToUniqueString("reg-for-ra"), 0x6301b475b8b91c02ULL);
   1.669 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.670 +                                             &caller_registers));
   1.671 +-  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
   1.672 +-  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
   1.673 ++  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers.get(ustr__ZDcfa()));
   1.674 ++  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers.get(ustr__ZDra()));
   1.675 + }
   1.676 + 
   1.677 + TEST_F(ParseHandler, RegisterRules) {
   1.678 +   handler.CFARule("reg-for-cfa");
   1.679 +   handler.RARule("reg-for-ra");
   1.680 +   handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1");
   1.681 +   handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2");
   1.682 +-  registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
   1.683 +-  registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
   1.684 +-  registers[ToUniqueString("reg-for-reg1")] = 0x06cde8e2ff062481ULL;
   1.685 +-  registers[ToUniqueString("reg-for-reg2")] = 0xff0c4f76403173e2ULL;
   1.686 ++  registers.set(ToUniqueString("reg-for-cfa"), 0x268a9a4a3821a797ULL);
   1.687 ++  registers.set(ToUniqueString("reg-for-ra"), 0x6301b475b8b91c02ULL);
   1.688 ++  registers.set(ToUniqueString("reg-for-reg1"), 0x06cde8e2ff062481ULL);
   1.689 ++  registers.set(ToUniqueString("reg-for-reg2"), 0xff0c4f76403173e2ULL);
   1.690 +   ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
   1.691 +                                             &caller_registers));
   1.692 +-  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
   1.693 +-  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
   1.694 +-  ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers[ToUniqueString("reg1")]);
   1.695 +-  ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers[ToUniqueString("reg2")]);
   1.696 ++  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers.get(ustr__ZDcfa()));
   1.697 ++  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers.get(ustr__ZDra()));
   1.698 ++  ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers.get(ToUniqueString("reg1")));
   1.699 ++  ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers.get(ToUniqueString("reg2")));
   1.700 + }
   1.701 + 
   1.702 + struct SimpleCFIWalkerFixture {
   1.703 +   struct RawContext {
   1.704 +     uint64_t r0, r1, r2, r3, r4, sp, pc;
   1.705 +   };
   1.706 +   enum Validity {
   1.707 +     R0_VALID = 0x01,
   1.708 +diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
   1.709 +--- a/src/processor/fast_source_line_resolver_unittest.cc
   1.710 ++++ b/src/processor/fast_source_line_resolver_unittest.cc
   1.711 +@@ -59,16 +59,17 @@
   1.712 + using google_breakpad::FromUniqueString;
   1.713 + using google_breakpad::ModuleSerializer;
   1.714 + using google_breakpad::ModuleComparer;
   1.715 + using google_breakpad::CFIFrameInfo;
   1.716 + using google_breakpad::CodeModule;
   1.717 + using google_breakpad::MemoryRegion;
   1.718 + using google_breakpad::StackFrame;
   1.719 + using google_breakpad::ToUniqueString;
   1.720 ++using google_breakpad::UniqueString;
   1.721 + using google_breakpad::WindowsFrameInfo;
   1.722 + using google_breakpad::linked_ptr;
   1.723 + using google_breakpad::scoped_ptr;
   1.724 + using google_breakpad::ustr__ZDcfa;
   1.725 + using google_breakpad::ustr__ZDra;
   1.726 + using google_breakpad::ustr__ZSebx;
   1.727 + using google_breakpad::ustr__ZSebp;
   1.728 + using google_breakpad::ustr__ZSedi;
   1.729 +@@ -125,27 +126,30 @@
   1.730 + };
   1.731 + 
   1.732 + // Verify that, for every association in ACTUAL, EXPECTED has the same
   1.733 + // association. (That is, ACTUAL's associations should be a subset of
   1.734 + // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
   1.735 + // ".cfa".
   1.736 + static bool VerifyRegisters(
   1.737 +     const char *file, int line,
   1.738 +-    const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
   1.739 +-    const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
   1.740 +-  CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
   1.741 ++    const std::map<const UniqueString*, uint32_t> &expected,
   1.742 ++    const CFIFrameInfo::RegisterValueMap<uint32_t> &actual_regmap) {
   1.743 ++  std::map<const UniqueString*, uint32_t> actual;
   1.744 ++  actual_regmap.copy_to_map(&actual);
   1.745 ++
   1.746 ++  std::map<const UniqueString*, uint32_t>::const_iterator a;
   1.747 +   a = actual.find(ustr__ZDcfa());
   1.748 +   if (a == actual.end())
   1.749 +     return false;
   1.750 +   a = actual.find(ustr__ZDra());
   1.751 +   if (a == actual.end())
   1.752 +     return false;
   1.753 +   for (a = actual.begin(); a != actual.end(); a++) {
   1.754 +-    CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
   1.755 ++    std::map<const UniqueString*, uint32_t>::const_iterator e =
   1.756 +       expected.find(a->first);
   1.757 +     if (e == expected.end()) {
   1.758 +       fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
   1.759 +               file, line, FromUniqueString(a->first), a->second);
   1.760 +       return false;
   1.761 +     }
   1.762 +     if (e->second != a->second) {
   1.763 +       fprintf(stderr,
   1.764 +@@ -286,86 +290,87 @@
   1.765 + 
   1.766 +   frame.instruction = 0x3e9f;
   1.767 +   frame.module = &module1;
   1.768 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.769 +   ASSERT_FALSE(cfi_frame_info.get());
   1.770 + 
   1.771 +   CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
   1.772 +   CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
   1.773 +-  CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
   1.774 ++  std::map<const UniqueString*, uint32_t> expected_caller_registers;
   1.775 +   MockMemoryRegion memory;
   1.776 + 
   1.777 +   // Regardless of which instruction evaluation takes place at, it
   1.778 +   // should produce the same values for the caller's registers.
   1.779 ++  // should produce the same values for the caller's registers.
   1.780 +   expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
   1.781 +-  expected_caller_registers[ustr__ZDra()]  = 0xf6438648;
   1.782 ++  expected_caller_registers[ustr__ZDra()] = 0xf6438648;
   1.783 +   expected_caller_registers[ustr__ZSebp()] = 0x10038;
   1.784 +   expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
   1.785 +   expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
   1.786 +   expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
   1.787 + 
   1.788 +   frame.instruction = 0x3d40;
   1.789 +   frame.module = &module1;
   1.790 +   current_registers.clear();
   1.791 +-  current_registers[ustr__ZSesp()] = 0x10018;
   1.792 +-  current_registers[ustr__ZSebp()] = 0x10038;
   1.793 +-  current_registers[ustr__ZSebx()] = 0x98ecadc3;
   1.794 +-  current_registers[ustr__ZSesi()] = 0x878f7524;
   1.795 +-  current_registers[ustr__ZSedi()] = 0x6312f9a5;
   1.796 ++  current_registers.set(ustr__ZSesp(), 0x10018);
   1.797 ++  current_registers.set(ustr__ZSebp(), 0x10038);
   1.798 ++  current_registers.set(ustr__ZSebx(), 0x98ecadc3);
   1.799 ++  current_registers.set(ustr__ZSesi(), 0x878f7524);
   1.800 ++  current_registers.set(ustr__ZSedi(), 0x6312f9a5);
   1.801 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.802 +   ASSERT_TRUE(cfi_frame_info.get());
   1.803 +   ASSERT_TRUE(cfi_frame_info.get()
   1.804 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.805 +                                           &caller_registers));
   1.806 +   ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
   1.807 +                               expected_caller_registers, caller_registers));
   1.808 + 
   1.809 +   frame.instruction = 0x3d41;
   1.810 +-  current_registers[ustr__ZSesp()] = 0x10014;
   1.811 ++  current_registers.set(ustr__ZSesp(), 0x10014);
   1.812 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.813 +   ASSERT_TRUE(cfi_frame_info.get());
   1.814 +   ASSERT_TRUE(cfi_frame_info.get()
   1.815 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.816 +                                           &caller_registers));
   1.817 +   ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
   1.818 +                               expected_caller_registers, caller_registers));
   1.819 + 
   1.820 +   frame.instruction = 0x3d43;
   1.821 +-  current_registers[ustr__ZSebp()] = 0x10014;
   1.822 ++  current_registers.set(ustr__ZSebp(), 0x10014);
   1.823 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.824 +   ASSERT_TRUE(cfi_frame_info.get());
   1.825 +   ASSERT_TRUE(cfi_frame_info.get()
   1.826 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.827 +                                           &caller_registers));
   1.828 +   VerifyRegisters(__FILE__, __LINE__,
   1.829 +                   expected_caller_registers, caller_registers);
   1.830 + 
   1.831 +   frame.instruction = 0x3d54;
   1.832 +-  current_registers[ustr__ZSebx()] = 0x6864f054U;
   1.833 ++  current_registers.set(ustr__ZSebx(), 0x6864f054U);
   1.834 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.835 +   ASSERT_TRUE(cfi_frame_info.get());
   1.836 +   ASSERT_TRUE(cfi_frame_info.get()
   1.837 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.838 +                                           &caller_registers));
   1.839 +   VerifyRegisters(__FILE__, __LINE__,
   1.840 +                   expected_caller_registers, caller_registers);
   1.841 + 
   1.842 +   frame.instruction = 0x3d5a;
   1.843 +-  current_registers[ustr__ZSesi()] = 0x6285f79aU;
   1.844 ++  current_registers.set(ustr__ZSesi(), 0x6285f79aU);
   1.845 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.846 +   ASSERT_TRUE(cfi_frame_info.get());
   1.847 +   ASSERT_TRUE(cfi_frame_info.get()
   1.848 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.849 +                                           &caller_registers));
   1.850 +   VerifyRegisters(__FILE__, __LINE__,
   1.851 +                   expected_caller_registers, caller_registers);
   1.852 + 
   1.853 +   frame.instruction = 0x3d84;
   1.854 +-  current_registers[ustr__ZSedi()] = 0x64061449U;
   1.855 ++  current_registers.set(ustr__ZSedi(), 0x64061449U);
   1.856 +   cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
   1.857 +   ASSERT_TRUE(cfi_frame_info.get());
   1.858 +   ASSERT_TRUE(cfi_frame_info.get()
   1.859 +               ->FindCallerRegs<uint32_t>(current_registers, memory,
   1.860 +                                           &caller_registers));
   1.861 +   VerifyRegisters(__FILE__, __LINE__,
   1.862 +                   expected_caller_registers, caller_registers);
   1.863 + 
   1.864 +diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h
   1.865 +--- a/src/processor/postfix_evaluator-inl.h
   1.866 ++++ b/src/processor/postfix_evaluator-inl.h
   1.867 +@@ -185,19 +185,19 @@
   1.868 +       return false;
   1.869 +     }
   1.870 +     if (identifier == ustr__empty() || Index(identifier,0) != '$') {
   1.871 +       BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " <<
   1.872 +                       identifier << ": " << expression;
   1.873 +       return false;
   1.874 +     }
   1.875 + 
   1.876 +-    (*dictionary_)[identifier] = value;
   1.877 ++    dictionary_->set(identifier, value);
   1.878 +     if (assigned)
   1.879 +-      (*assigned)[identifier] = true;
   1.880 ++      assigned->set(identifier, true);
   1.881 +   } else {
   1.882 +     // Push it onto the stack as-is, but first convert it either to a
   1.883 +     // ValueType (if a literal) or to a UniqueString* (if an identifier).
   1.884 +     //
   1.885 +     // First, try to treat the value as a literal. Literals may have leading
   1.886 +     // '-' sign, and the entire remaining string must be parseable as
   1.887 +     // ValueType. If this isn't possible, it can't be a literal, so treat it
   1.888 +     // as an identifier instead.
   1.889 +@@ -300,28 +300,28 @@
   1.890 + 
   1.891 +       return PopValue(result);
   1.892 +     }
   1.893 + 
   1.894 +     // Simple-form expressions
   1.895 +     case Module::kExprSimple:
   1.896 +     case Module::kExprSimpleMem: {
   1.897 +       // Look up the base value
   1.898 +-      typename DictionaryType::const_iterator iterator
   1.899 +-        = dictionary_->find(expr.ident_);
   1.900 +-      if (iterator == dictionary_->end()) {
   1.901 ++      bool found = false;
   1.902 ++      ValueType v = dictionary_->get(&found, expr.ident_);
   1.903 ++      if (!found) {
   1.904 +         // The identifier wasn't found in the dictionary.  Don't imply any
   1.905 +         // default value, just fail.
   1.906 +-        BPLOG(INFO) << "Identifier " << expr.ident_
   1.907 ++        BPLOG(INFO) << "Identifier " << FromUniqueString(expr.ident_)
   1.908 +                     << " not in dictionary (kExprSimple{Mem})";
   1.909 +         return false;
   1.910 +       }
   1.911 + 
   1.912 +       // Form the sum
   1.913 +-      ValueType sum = iterator->second + (int64_t)expr.offset_;
   1.914 ++      ValueType sum = v + (int64_t)expr.offset_;
   1.915 + 
   1.916 +       // and dereference if necessary
   1.917 +       if (expr.how_ == Module::kExprSimpleMem) {
   1.918 +         ValueType derefd;
   1.919 +         if (!memory_ || !memory_->GetMemoryAtAddress(sum, &derefd)) {
   1.920 +           return false;
   1.921 +         }
   1.922 +         *result = derefd;
   1.923 +@@ -368,27 +368,27 @@
   1.924 +   if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) {
   1.925 +     return false;
   1.926 +   } else if (result == POP_RESULT_VALUE) {
   1.927 +     // This is the easy case.
   1.928 +     *value = literal;
   1.929 +   } else {  // result == POP_RESULT_IDENTIFIER
   1.930 +     // There was an identifier at the top of the stack.  Resolve it to a
   1.931 +     // value by looking it up in the dictionary.
   1.932 +-    typename DictionaryType::const_iterator iterator =
   1.933 +-        dictionary_->find(token);
   1.934 +-    if (iterator == dictionary_->end()) {
   1.935 ++    bool found = false;
   1.936 ++    ValueType v = dictionary_->get(&found, token);
   1.937 ++    if (!found) {
   1.938 +       // The identifier wasn't found in the dictionary.  Don't imply any
   1.939 +       // default value, just fail.
   1.940 +       BPLOG(INFO) << "Identifier " << FromUniqueString(token)
   1.941 +                   << " not in dictionary";
   1.942 +       return false;
   1.943 +     }
   1.944 + 
   1.945 +-    *value = iterator->second;
   1.946 ++    *value = v;
   1.947 +   }
   1.948 + 
   1.949 +   return true;
   1.950 + }
   1.951 + 
   1.952 + 
   1.953 + template<typename ValueType>
   1.954 + bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1,
   1.955 +diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
   1.956 +--- a/src/processor/postfix_evaluator.h
   1.957 ++++ b/src/processor/postfix_evaluator.h
   1.958 +@@ -93,18 +93,18 @@
   1.959 +   StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; }
   1.960 +   bool isValue;
   1.961 +   union { ValueType val; const UniqueString* ustr; } u;
   1.962 + };
   1.963 + 
   1.964 + template<typename ValueType>
   1.965 + class PostfixEvaluator {
   1.966 +  public:
   1.967 +-  typedef map<const UniqueString*, ValueType> DictionaryType;
   1.968 +-  typedef map<const UniqueString*, bool> DictionaryValidityType;
   1.969 ++  typedef UniqueStringMap<ValueType> DictionaryType;
   1.970 ++  typedef UniqueStringMap<bool>      DictionaryValidityType;
   1.971 + 
   1.972 +   // Create a PostfixEvaluator object that may be used (with Evaluate) on
   1.973 +   // one or more expressions.  PostfixEvaluator does not take ownership of
   1.974 +   // either argument.  |memory| may be NULL, in which case dereferencing
   1.975 +   // (^) will not be supported.  |dictionary| may be NULL, but evaluation
   1.976 +   // will fail in that case unless set_dictionary is used before calling
   1.977 +   // Evaluate.
   1.978 +   PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory)
   1.979 +diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
   1.980 +--- a/src/processor/postfix_evaluator_unittest.cc
   1.981 ++++ b/src/processor/postfix_evaluator_unittest.cc
   1.982 +@@ -178,22 +178,22 @@
   1.983 +   validate_data_0[ToUniqueString("$rAdd3")]  = 4;
   1.984 +   validate_data_0[ToUniqueString("$rMul2")]  = 54;
   1.985 + 
   1.986 +   // The second test set simulates a couple of MSVC program strings.
   1.987 +   // The data is fudged a little bit because the tests use FakeMemoryRegion
   1.988 +   // instead of a real stack snapshot, but the program strings are real and
   1.989 +   // the implementation doesn't know or care that the data is not real.
   1.990 +   PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
   1.991 +-  dictionary_1[ustr__ZSebp()] = 0xbfff0010;
   1.992 +-  dictionary_1[ustr__ZSeip()] = 0x10000000;
   1.993 +-  dictionary_1[ustr__ZSesp()] = 0xbfff0000;
   1.994 +-  dictionary_1[ustr__ZDcbSavedRegs()] = 4;
   1.995 +-  dictionary_1[ustr__ZDcbParams()] = 4;
   1.996 +-  dictionary_1[ustr__ZDraSearchStart()] = 0xbfff0020;
   1.997 ++  dictionary_1.set(ustr__ZSebp(), 0xbfff0010);
   1.998 ++  dictionary_1.set(ustr__ZSeip(), 0x10000000);
   1.999 ++  dictionary_1.set(ustr__ZSesp(), 0xbfff0000);
  1.1000 ++  dictionary_1.set(ustr__ZDcbSavedRegs(), 4);
  1.1001 ++  dictionary_1.set(ustr__ZDcbParams(), 4);
  1.1002 ++  dictionary_1.set(ustr__ZDraSearchStart(), 0xbfff0020);
  1.1003 +   const EvaluateTest evaluate_tests_1[] = {
  1.1004 +     { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
  1.1005 +       "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
  1.1006 +     // Intermediate state: $T0  = 0xbfff0010, $eip = 0xbfff0015,
  1.1007 +     //                     $ebp = 0xbfff0011, $esp = 0xbfff0018,
  1.1008 +     //                     $L   = 0xbfff000c, $P   = 0xbfff001c
  1.1009 +     { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
  1.1010 +       "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =",
  1.1011 +@@ -273,70 +273,65 @@
  1.1012 +     for (map<const UniqueString*, unsigned int>::const_iterator
  1.1013 +             validate_iterator =
  1.1014 +             evaluate_test_set->validate_data->begin();
  1.1015 +         validate_iterator != evaluate_test_set->validate_data->end();
  1.1016 +         ++validate_iterator) {
  1.1017 +       const UniqueString* identifier = validate_iterator->first;
  1.1018 +       unsigned int expected_value = validate_iterator->second;
  1.1019 + 
  1.1020 +-      map<const UniqueString*, unsigned int>::const_iterator
  1.1021 +-          dictionary_iterator =
  1.1022 +-          evaluate_test_set->dictionary->find(identifier);
  1.1023 +-
  1.1024 +       // The identifier must exist in the dictionary.
  1.1025 +-      if (dictionary_iterator == evaluate_test_set->dictionary->end()) {
  1.1026 ++      if (!evaluate_test_set->dictionary->have(identifier)) {
  1.1027 +         fprintf(stderr, "FAIL: evaluate test set %d/%d, "
  1.1028 +                         "validate identifier \"%s\", "
  1.1029 +                         "expected %d, observed not found\n",
  1.1030 +                 evaluate_test_set_index, evaluate_test_set_count,
  1.1031 +                 FromUniqueString(identifier), expected_value);
  1.1032 +         return false;
  1.1033 +       }
  1.1034 + 
  1.1035 +       // The value in the dictionary must be the same as the expected value.
  1.1036 +-      unsigned int observed_value = dictionary_iterator->second;
  1.1037 ++      unsigned int observed_value =
  1.1038 ++          evaluate_test_set->dictionary->get(identifier);
  1.1039 +       if (expected_value != observed_value) {
  1.1040 +         fprintf(stderr, "FAIL: evaluate test set %d/%d, "
  1.1041 +                         "validate identifier \"%s\", "
  1.1042 +                         "expected %d, observed %d\n",
  1.1043 +                 evaluate_test_set_index, evaluate_test_set_count,
  1.1044 +                 FromUniqueString(identifier), expected_value, observed_value);
  1.1045 +         return false;
  1.1046 +       }
  1.1047 + 
  1.1048 +       // The value must be set in the "assigned" dictionary if it was a
  1.1049 +       // variable.  It must not have been assigned if it was a constant.
  1.1050 +       bool expected_assigned = FromUniqueString(identifier)[0] == '$';
  1.1051 +       bool observed_assigned = false;
  1.1052 +-      PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator
  1.1053 +-          iterator_assigned = assigned.find(identifier);
  1.1054 +-      if (iterator_assigned != assigned.end()) {
  1.1055 +-        observed_assigned = iterator_assigned->second;
  1.1056 ++      if (assigned.have(identifier)) {
  1.1057 ++        observed_assigned = assigned.get(identifier);
  1.1058 +       }
  1.1059 +       if (expected_assigned != observed_assigned) {
  1.1060 +         fprintf(stderr, "FAIL: evaluate test set %d/%d, "
  1.1061 +                         "validate assignment of \"%s\", "
  1.1062 +                         "expected %d, observed %d\n",
  1.1063 +                 evaluate_test_set_index, evaluate_test_set_count,
  1.1064 +                 FromUniqueString(identifier), expected_assigned,
  1.1065 +                 observed_assigned);
  1.1066 +         return false;
  1.1067 +       }
  1.1068 +     }
  1.1069 +   }
  1.1070 + 
  1.1071 +   // EvaluateForValue tests.
  1.1072 +   PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
  1.1073 +-  dictionary_2[ustr__ZSebp()] = 0xbfff0010;
  1.1074 +-  dictionary_2[ustr__ZSeip()] = 0x10000000;
  1.1075 +-  dictionary_2[ustr__ZSesp()] = 0xbfff0000;
  1.1076 +-  dictionary_2[ustr__ZDcbSavedRegs()] = 4;
  1.1077 +-  dictionary_2[ustr__ZDcbParams()] = 4;
  1.1078 +-  dictionary_2[ustr__ZDraSearchStart()] = 0xbfff0020;
  1.1079 ++  dictionary_2.set(ustr__ZSebp(), 0xbfff0010);
  1.1080 ++  dictionary_2.set(ustr__ZSeip(), 0x10000000);
  1.1081 ++  dictionary_2.set(ustr__ZSesp(), 0xbfff0000);
  1.1082 ++  dictionary_2.set(ustr__ZDcbSavedRegs(), 4);
  1.1083 ++  dictionary_2.set(ustr__ZDcbParams(), 4);
  1.1084 ++  dictionary_2.set(ustr__ZDraSearchStart(), 0xbfff0020);
  1.1085 +   const EvaluateForValueTest evaluate_for_value_tests_2[] = {
  1.1086 +     { "28907223",               true,  28907223 },      // simple constant
  1.1087 +     { "89854293 40010015 +",    true,  89854293 + 40010015 }, // arithmetic
  1.1088 +     { "-870245 8769343 +",      true,  7899098 },       // negative constants
  1.1089 +     { "$ebp $esp - $eip +",     true,  0x10000010 },    // variable references
  1.1090 +     { "18929794 34015074",      false, 0 },             // too many values
  1.1091 +     { "$ebp $ebp 4 - =",        false, 0 },             // too few values
  1.1092 +     { "$new $eip = $new",       true,  0x10000000 },    // make new variable
  1.1093 +@@ -370,41 +365,43 @@
  1.1094 +     if (test->evaluable && result != test->value) {
  1.1095 +       fprintf(stderr, "FAIL: evaluate for value test %d, "
  1.1096 +               "expected value to be 0x%x, but it was 0x%x\n",
  1.1097 +               i, test->value, result);
  1.1098 +       return false;
  1.1099 +     }
  1.1100 +   }
  1.1101 + 
  1.1102 ++  map<const UniqueString*, unsigned int> dictionary_2_map;
  1.1103 ++  dictionary_2.copy_to_map(&dictionary_2_map);
  1.1104 +   for (map<const UniqueString*, unsigned int>::iterator v =
  1.1105 +          validate_data_2.begin();
  1.1106 +        v != validate_data_2.end(); v++) {
  1.1107 +     map<const UniqueString*, unsigned int>::iterator a =
  1.1108 +-        dictionary_2.find(v->first);
  1.1109 +-    if (a == dictionary_2.end()) {
  1.1110 ++        dictionary_2_map.find(v->first);
  1.1111 ++    if (a == dictionary_2_map.end()) {
  1.1112 +       fprintf(stderr, "FAIL: evaluate for value dictionary check: "
  1.1113 +               "expected dict[\"%s\"] to be 0x%x, but it was unset\n",
  1.1114 +               FromUniqueString(v->first), v->second);
  1.1115 +       return false;
  1.1116 +     } else if (a->second != v->second) {
  1.1117 +       fprintf(stderr, "FAIL: evaluate for value dictionary check: "
  1.1118 +               "expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
  1.1119 +               FromUniqueString(v->first), v->second, a->second);
  1.1120 +       return false;
  1.1121 +-    } 
  1.1122 +-    dictionary_2.erase(a);
  1.1123 ++    }
  1.1124 ++    dictionary_2_map.erase(a);
  1.1125 +   }
  1.1126 +-  
  1.1127 ++
  1.1128 +   map<const UniqueString*, unsigned int>::iterator remaining =
  1.1129 +-      dictionary_2.begin();
  1.1130 +-  if (remaining != dictionary_2.end()) {
  1.1131 ++      dictionary_2_map.begin();
  1.1132 ++  if (remaining != dictionary_2_map.end()) {
  1.1133 +     fprintf(stderr, "FAIL: evaluation of test expressions put unexpected "
  1.1134 +             "values in dictionary:\n");
  1.1135 +-    for (; remaining != dictionary_2.end(); remaining++)
  1.1136 ++    for (; remaining != dictionary_2_map.end(); remaining++)
  1.1137 +       fprintf(stderr, "    dict[\"%s\"] == 0x%x\n",
  1.1138 +               FromUniqueString(remaining->first), remaining->second);
  1.1139 +     return false;
  1.1140 +   }
  1.1141 + 
  1.1142 +   return true;
  1.1143 + }
  1.1144 + 
  1.1145 +diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
  1.1146 +--- a/src/processor/stackwalker_arm.cc
  1.1147 ++++ b/src/processor/stackwalker_arm.cc
  1.1148 +@@ -97,70 +97,70 @@
  1.1149 +     ToUniqueString("fps"), ToUniqueString("cpsr"),
  1.1150 +     NULL
  1.1151 +   };
  1.1152 + 
  1.1153 +   // Populate a dictionary with the valid register values in last_frame.
  1.1154 +   CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
  1.1155 +   for (int i = 0; register_names[i]; i++)
  1.1156 +     if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
  1.1157 +-      callee_registers[register_names[i]] = last_frame->context.iregs[i];
  1.1158 ++      callee_registers.set(register_names[i], last_frame->context.iregs[i]);
  1.1159 + 
  1.1160 +   // Use the STACK CFI data to recover the caller's register values.
  1.1161 +   CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
  1.1162 +   if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
  1.1163 +                                       &caller_registers))
  1.1164 +     return NULL;
  1.1165 + 
  1.1166 +   // Construct a new stack frame given the values the CFI recovered.
  1.1167 +   scoped_ptr<StackFrameARM> frame(new StackFrameARM());
  1.1168 +   for (int i = 0; register_names[i]; i++) {
  1.1169 +-    CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
  1.1170 +-      caller_registers.find(register_names[i]);
  1.1171 +-    if (entry != caller_registers.end()) {
  1.1172 ++    bool found = false;
  1.1173 ++    uint32_t v = caller_registers.get(&found, register_names[i]);
  1.1174 ++    if (found) {
  1.1175 +       // We recovered the value of this register; fill the context with the
  1.1176 +       // value from caller_registers.
  1.1177 +       frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
  1.1178 +-      frame->context.iregs[i] = entry->second;
  1.1179 ++      frame->context.iregs[i] = v;
  1.1180 +     } else if (4 <= i && i <= 11 && (last_frame->context_validity &
  1.1181 +                                      StackFrameARM::RegisterValidFlag(i))) {
  1.1182 +       // If the STACK CFI data doesn't mention some callee-saves register, and
  1.1183 +       // it is valid in the callee, assume the callee has not yet changed it.
  1.1184 +       // Registers r4 through r11 are callee-saves, according to the Procedure
  1.1185 +       // Call Standard for the ARM Architecture, which the Linux ABI follows.
  1.1186 +       frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
  1.1187 +       frame->context.iregs[i] = last_frame->context.iregs[i];
  1.1188 +     }
  1.1189 +   }
  1.1190 +   // If the CFI doesn't recover the PC explicitly, then use .ra.
  1.1191 +   if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
  1.1192 +-    CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
  1.1193 +-      caller_registers.find(ustr__ZDra());
  1.1194 +-    if (entry != caller_registers.end()) {
  1.1195 ++    bool found = false;
  1.1196 ++    uint32_t v = caller_registers.get(&found, ustr__ZDra());
  1.1197 ++    if (found) {
  1.1198 +       if (fp_register_ == -1) {
  1.1199 +         frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
  1.1200 +-        frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second;
  1.1201 ++        frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = v;
  1.1202 +       } else {
  1.1203 +         // The CFI updated the link register and not the program counter.
  1.1204 +         // Handle getting the program counter from the link register.
  1.1205 +         frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
  1.1206 +         frame->context_validity |= StackFrameARM::CONTEXT_VALID_LR;
  1.1207 +-        frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = entry->second;
  1.1208 ++        frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = v;
  1.1209 +         frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
  1.1210 +             last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
  1.1211 +       }
  1.1212 +     }
  1.1213 +   }
  1.1214 +   // If the CFI doesn't recover the SP explicitly, then use .cfa.
  1.1215 +   if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
  1.1216 +-    CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
  1.1217 +-      caller_registers.find(ustr__ZDcfa());
  1.1218 +-    if (entry != caller_registers.end()) {
  1.1219 ++    bool found = false;
  1.1220 ++    uint32_t v = caller_registers.get(&found, ustr__ZDcfa());
  1.1221 ++    if (found) {
  1.1222 +       frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP;
  1.1223 +-      frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second;
  1.1224 ++      frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = v;
  1.1225 +     }
  1.1226 +   }
  1.1227 + 
  1.1228 +   // If we didn't recover the PC and the SP, then the frame isn't very useful.
  1.1229 +   static const int essentials = (StackFrameARM::CONTEXT_VALID_SP
  1.1230 +                                  | StackFrameARM::CONTEXT_VALID_PC);
  1.1231 +   if ((frame->context_validity & essentials) != essentials)
  1.1232 +     return NULL;
  1.1233 +diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
  1.1234 +--- a/src/processor/stackwalker_x86.cc
  1.1235 ++++ b/src/processor/stackwalker_x86.cc
  1.1236 +@@ -194,26 +194,26 @@
  1.1237 +     }
  1.1238 +   }
  1.1239 + 
  1.1240 +   // Set up the dictionary for the PostfixEvaluator.  %ebp and %esp are used
  1.1241 +   // in each program string, and their previous values are known, so set them
  1.1242 +   // here.
  1.1243 +   PostfixEvaluator<uint32_t>::DictionaryType dictionary;
  1.1244 +   // Provide the current register values.
  1.1245 +-  dictionary[ustr__ZSebp()] = last_frame->context.ebp;
  1.1246 +-  dictionary[ustr__ZSesp()] = last_frame->context.esp;
  1.1247 ++  dictionary.set(ustr__ZSebp(), last_frame->context.ebp);
  1.1248 ++  dictionary.set(ustr__ZSesp(), last_frame->context.esp);
  1.1249 +   // Provide constants from the debug info for last_frame and its callee.
  1.1250 +   // .cbCalleeParams is a Breakpad extension that allows us to use the
  1.1251 +   // PostfixEvaluator engine when certain types of debugging information
  1.1252 +   // are present without having to write the constants into the program
  1.1253 +   // string as literals.
  1.1254 +-  dictionary[ustr__ZDcbCalleeParams()] = last_frame_callee_parameter_size;
  1.1255 +-  dictionary[ustr__ZDcbSavedRegs()] = last_frame_info->saved_register_size;
  1.1256 +-  dictionary[ustr__ZDcbLocals()] = last_frame_info->local_size;
  1.1257 ++  dictionary.set(ustr__ZDcbCalleeParams(), last_frame_callee_parameter_size);
  1.1258 ++  dictionary.set(ustr__ZDcbSavedRegs(), last_frame_info->saved_register_size);
  1.1259 ++  dictionary.set(ustr__ZDcbLocals(), last_frame_info->local_size);
  1.1260 + 
  1.1261 +   uint32_t raSearchStart = last_frame->context.esp +
  1.1262 +                             last_frame_callee_parameter_size +
  1.1263 +                             last_frame_info->local_size +
  1.1264 +                             last_frame_info->saved_register_size;
  1.1265 + 
  1.1266 +   uint32_t raSearchStartOld = raSearchStart;
  1.1267 +   uint32_t found = 0;  // dummy value
  1.1268 +@@ -232,20 +232,20 @@
  1.1269 +     // Skip one slot from the stack and do another scan in order to get the
  1.1270 +     // actual return address.
  1.1271 +     raSearchStart += 4;
  1.1272 +     ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
  1.1273 +   }
  1.1274 + 
  1.1275 +   // The difference between raSearch and raSearchStart is unknown,
  1.1276 +   // but making them the same seems to work well in practice.
  1.1277 +-  dictionary[ustr__ZDraSearchStart()] = raSearchStart;
  1.1278 +-  dictionary[ustr__ZDraSearch()] = raSearchStart;
  1.1279 ++  dictionary.set(ustr__ZDraSearchStart(), raSearchStart);
  1.1280 ++  dictionary.set(ustr__ZDraSearch(), raSearchStart);
  1.1281 + 
  1.1282 +-  dictionary[ustr__ZDcbParams()] = last_frame_info->parameter_size;
  1.1283 ++  dictionary.set(ustr__ZDcbParams(), last_frame_info->parameter_size);
  1.1284 + 
  1.1285 +   // Decide what type of program string to use. The program string is in
  1.1286 +   // postfix notation and will be passed to PostfixEvaluator::Evaluate.
  1.1287 +   // Given the dictionary and the program string, it is possible to compute
  1.1288 +   // the return address and the values of other registers in the calling
  1.1289 +   // function. Because of bugs described below, the stack may need to be
  1.1290 +   // scanned for these values. The results of program string evaluation
  1.1291 +   // will be used to determine whether to scan for better values.
  1.1292 +@@ -325,18 +325,18 @@
  1.1293 +   }
  1.1294 + 
  1.1295 +   // Now crank it out, making sure that the program string set at least the
  1.1296 +   // two required variables.
  1.1297 +   PostfixEvaluator<uint32_t> evaluator =
  1.1298 +       PostfixEvaluator<uint32_t>(&dictionary, memory_);
  1.1299 +   PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity;
  1.1300 +   if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
  1.1301 +-      dictionary_validity.find(ustr__ZSeip()) == dictionary_validity.end() ||
  1.1302 +-      dictionary_validity.find(ustr__ZSesp()) == dictionary_validity.end()) {
  1.1303 ++      !dictionary_validity.have(ustr__ZSeip()) ||
  1.1304 ++      !dictionary_validity.have(ustr__ZSesp())) {
  1.1305 +     // Program string evaluation failed. It may be that %eip is not somewhere
  1.1306 +     // with stack frame info, and %ebp is pointing to non-stack memory, so
  1.1307 +     // our evaluation couldn't succeed. We'll scan the stack for a return
  1.1308 +     // address. This can happen if the stack is in a module for which
  1.1309 +     // we don't have symbols, and that module is compiled without a
  1.1310 +     // frame pointer.
  1.1311 +     uint32_t location_start = last_frame->context.esp;
  1.1312 +     uint32_t location, eip;
  1.1313 +@@ -344,69 +344,70 @@
  1.1314 +       // if we can't find an instruction pointer even with stack scanning,
  1.1315 +       // give up.
  1.1316 +       return NULL;
  1.1317 +     }
  1.1318 + 
  1.1319 +     // This seems like a reasonable return address. Since program string
  1.1320 +     // evaluation failed, use it and set %esp to the location above the
  1.1321 +     // one where the return address was found.
  1.1322 +-    dictionary[ustr__ZSeip()] = eip;
  1.1323 +-    dictionary[ustr__ZSesp()] = location + 4;
  1.1324 ++    dictionary.set(ustr__ZSeip(), eip);
  1.1325 ++    dictionary.set(ustr__ZSesp(), location + 4);
  1.1326 +     trust = StackFrame::FRAME_TRUST_SCAN;
  1.1327 +   }
  1.1328 + 
  1.1329 +   // Since this stack frame did not use %ebp in a traditional way,
  1.1330 +   // locating the return address isn't entirely deterministic. In that
  1.1331 +   // case, the stack can be scanned to locate the return address.
  1.1332 +   //
  1.1333 +   // However, if program string evaluation resulted in both %eip and
  1.1334 +   // %ebp values of 0, trust that the end of the stack has been
  1.1335 +   // reached and don't scan for anything else.
  1.1336 +-  if (dictionary[ustr__ZSeip()] != 0 || dictionary[ustr__ZSebp()] != 0) {
  1.1337 ++  if (dictionary.get(ustr__ZSeip()) != 0 ||
  1.1338 ++      dictionary.get(ustr__ZSebp()) != 0) {
  1.1339 +     int offset = 0;
  1.1340 + 
  1.1341 +     // This scan can only be done if a CodeModules object is available, to
  1.1342 +     // check that candidate return addresses are in fact inside a module.
  1.1343 +     //
  1.1344 +     // TODO(mmentovai): This ignores dynamically-generated code.  One possible
  1.1345 +     // solution is to check the minidump's memory map to see if the candidate
  1.1346 +     // %eip value comes from a mapped executable page, although this would
  1.1347 +     // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad
  1.1348 +     // client doesn't currently write (it would need to call MiniDumpWriteDump
  1.1349 +     // with the MiniDumpWithFullMemoryInfo type bit set).  Even given this
  1.1350 +     // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
  1.1351 +     // an independent execute privilege on memory pages.
  1.1352 + 
  1.1353 +-    uint32_t eip = dictionary[ustr__ZSeip()];
  1.1354 ++    uint32_t eip = dictionary.get(ustr__ZSeip());
  1.1355 +     if (modules_ && !modules_->GetModuleForAddress(eip)) {
  1.1356 +       // The instruction pointer at .raSearchStart was invalid, so start
  1.1357 +       // looking one 32-bit word above that location.
  1.1358 +-      uint32_t location_start = dictionary[ustr__ZDraSearchStart()] + 4;
  1.1359 ++      uint32_t location_start = dictionary.get(ustr__ZDraSearchStart()) + 4;
  1.1360 +       uint32_t location;
  1.1361 +       if (ScanForReturnAddress(location_start, &location, &eip)) {
  1.1362 +         // This is a better return address that what program string
  1.1363 +         // evaluation found.  Use it, and set %esp to the location above the
  1.1364 +         // one where the return address was found.
  1.1365 +-        dictionary[ustr__ZSeip()] = eip;
  1.1366 +-        dictionary[ustr__ZSesp()] = location + 4;
  1.1367 ++        dictionary.set(ustr__ZSeip(), eip);
  1.1368 ++        dictionary.set(ustr__ZSesp(), location + 4);
  1.1369 +         offset = location - location_start;
  1.1370 +         trust = StackFrame::FRAME_TRUST_CFI_SCAN;
  1.1371 +       }
  1.1372 +     }
  1.1373 + 
  1.1374 +     if (recover_ebp) {
  1.1375 +       // When trying to recover the previous value of the frame pointer (%ebp),
  1.1376 +       // start looking at the lowest possible address in the saved-register
  1.1377 +       // area, and look at the entire saved register area, increased by the
  1.1378 +       // size of |offset| to account for additional data that may be on the
  1.1379 +       // stack.  The scan is performed from the highest possible address to
  1.1380 +       // the lowest, because the expectation is that the function's prolog
  1.1381 +       // would have saved %ebp early.
  1.1382 +-      uint32_t ebp = dictionary[ustr__ZSebp()];
  1.1383 ++      uint32_t ebp = dictionary.get(ustr__ZSebp());
  1.1384 + 
  1.1385 +       // When a scan for return address is used, it is possible to skip one or
  1.1386 +       // more frames (when return address is not in a known module).  One
  1.1387 +       // indication for skipped frames is when the value of %ebp is lower than
  1.1388 +       // the location of the return address on the stack
  1.1389 +       bool has_skipped_frames =
  1.1390 +         (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset);
  1.1391 + 
  1.1392 +@@ -420,49 +421,49 @@
  1.1393 +              location >= location_end;
  1.1394 +              location -= 4) {
  1.1395 +           if (!memory_->GetMemoryAtAddress(location, &ebp))
  1.1396 +             break;
  1.1397 + 
  1.1398 +           if (memory_->GetMemoryAtAddress(ebp, &value)) {
  1.1399 +             // The candidate value is a pointer to the same memory region
  1.1400 +             // (the stack).  Prefer it as a recovered %ebp result.
  1.1401 +-            dictionary[ustr__ZSebp()] = ebp;
  1.1402 ++            dictionary.set(ustr__ZSebp(), ebp);
  1.1403 +             break;
  1.1404 +           }
  1.1405 +         }
  1.1406 +       }
  1.1407 +     }
  1.1408 +   }
  1.1409 + 
  1.1410 +   // Create a new stack frame (ownership will be transferred to the caller)
  1.1411 +   // and fill it in.
  1.1412 +   StackFrameX86* frame = new StackFrameX86();
  1.1413 + 
  1.1414 +   frame->trust = trust;
  1.1415 +   frame->context = last_frame->context;
  1.1416 +-  frame->context.eip = dictionary[ustr__ZSeip()];
  1.1417 +-  frame->context.esp = dictionary[ustr__ZSesp()];
  1.1418 +-  frame->context.ebp = dictionary[ustr__ZSebp()];
  1.1419 ++  frame->context.eip = dictionary.get(ustr__ZSeip());
  1.1420 ++  frame->context.esp = dictionary.get(ustr__ZSesp());
  1.1421 ++  frame->context.ebp = dictionary.get(ustr__ZSebp());
  1.1422 +   frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
  1.1423 +                                 StackFrameX86::CONTEXT_VALID_ESP |
  1.1424 +                                 StackFrameX86::CONTEXT_VALID_EBP;
  1.1425 + 
  1.1426 +   // These are nonvolatile (callee-save) registers, and the program string
  1.1427 +   // may have filled them in.
  1.1428 +-  if (dictionary_validity.find(ustr__ZSebx()) != dictionary_validity.end()) {
  1.1429 +-    frame->context.ebx = dictionary[ustr__ZSebx()];
  1.1430 ++  if (dictionary_validity.have(ustr__ZSebx())) {
  1.1431 ++    frame->context.ebx = dictionary.get(ustr__ZSebx());
  1.1432 +     frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX;
  1.1433 +   }
  1.1434 +-  if (dictionary_validity.find(ustr__ZSesi()) != dictionary_validity.end()) {
  1.1435 +-    frame->context.esi = dictionary[ustr__ZSesi()];
  1.1436 ++  if (dictionary_validity.have(ustr__ZSesi())) {
  1.1437 ++    frame->context.esi = dictionary.get(ustr__ZSesi());
  1.1438 +     frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI;
  1.1439 +   }
  1.1440 +-  if (dictionary_validity.find(ustr__ZSedi()) != dictionary_validity.end()) {
  1.1441 +-    frame->context.edi = dictionary[ustr__ZSedi()];
  1.1442 ++  if (dictionary_validity.have(ustr__ZSedi())) {
  1.1443 ++    frame->context.edi = dictionary.get(ustr__ZSedi());
  1.1444 +     frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
  1.1445 +   }
  1.1446 + 
  1.1447 +   return frame;
  1.1448 + }
  1.1449 + 
  1.1450 + StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
  1.1451 +     const vector<StackFrame*> &frames,

mercurial