2013-02-06 16:01:57 -08:00
|
|
|
# HG changeset patch
|
2013-02-07 09:56:27 -08:00
|
|
|
# User Ted Mielczarek <ted.mielczarek@gmail.com>
|
|
|
|
# Date 1360255134 18000
|
|
|
|
# Node ID 97572beba4ad7fa4f76c3d1871d2001839a65b32
|
|
|
|
# Parent 229852c0b835929a56f207996034cf072307b343
|
2013-02-06 16:01:57 -08:00
|
|
|
Rework PostfixEvaluator to use UniqueStringMap
|
|
|
|
R=ted
|
|
|
|
|
|
|
|
diff --git a/src/common/unique_string.h b/src/common/unique_string.h
|
|
|
|
--- a/src/common/unique_string.h
|
|
|
|
+++ b/src/common/unique_string.h
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -30,6 +30,7 @@
|
|
|
|
#ifndef COMMON_UNIQUE_STRING_H_
|
|
|
|
#define COMMON_UNIQUE_STRING_H_
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
+#include <map>
|
2013-02-07 09:56:27 -08:00
|
|
|
#include <string>
|
2013-02-06 16:01:57 -08:00
|
|
|
#include "common/using_std_string.h"
|
|
|
|
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -234,6 +235,107 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
return us;
|
|
|
|
}
|
|
|
|
|
|
|
|
+template <typename ValueType>
|
|
|
|
+class UniqueStringMap
|
|
|
|
+{
|
|
|
|
+ private:
|
|
|
|
+ static const int N_FIXED = 10;
|
|
|
|
+
|
|
|
|
+ public:
|
2013-02-07 09:56:27 -08:00
|
|
|
+ UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {};
|
|
|
|
+ ~UniqueStringMap() {};
|
2013-02-06 16:01:57 -08:00
|
|
|
+
|
|
|
|
+ // Empty out the map.
|
2013-02-07 09:56:27 -08:00
|
|
|
+ void clear() {
|
|
|
|
+ ++n_clears_;
|
2013-02-06 16:01:57 -08:00
|
|
|
+ map_.clear();
|
|
|
|
+ n_fixed_ = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Do "map[ix] = v".
|
2013-02-07 09:56:27 -08:00
|
|
|
+ void set(const UniqueString* ix, ValueType v) {
|
|
|
|
+ ++n_sets_;
|
2013-02-06 16:01:57 -08:00
|
|
|
+ int i;
|
2013-02-07 09:56:27 -08:00
|
|
|
+ for (i = 0; i < n_fixed_; ++i) {
|
2013-02-06 16:01:57 -08:00
|
|
|
+ if (fixed_keys_[i] == ix) {
|
|
|
|
+ fixed_vals_[i] = v;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (n_fixed_ < N_FIXED) {
|
|
|
|
+ i = n_fixed_;
|
|
|
|
+ fixed_keys_[i] = ix;
|
|
|
|
+ fixed_vals_[i] = v;
|
2013-02-07 09:56:27 -08:00
|
|
|
+ ++n_fixed_;
|
2013-02-06 16:01:57 -08:00
|
|
|
+ } else {
|
|
|
|
+ map_[ix] = v;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Lookup 'ix' in the map, and also return a success/fail boolean.
|
2013-02-07 09:56:27 -08:00
|
|
|
+ ValueType get(/*OUT*/bool* have, const UniqueString* ix) const {
|
|
|
|
+ ++n_gets_;
|
2013-02-06 16:01:57 -08:00
|
|
|
+ int i;
|
2013-02-07 09:56:27 -08:00
|
|
|
+ for (i = 0; i < n_fixed_; ++i) {
|
2013-02-06 16:01:57 -08:00
|
|
|
+ if (fixed_keys_[i] == ix) {
|
|
|
|
+ *have = true;
|
|
|
|
+ return fixed_vals_[i];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ typename std::map<const UniqueString*, ValueType>::const_iterator it
|
2013-02-07 09:56:27 -08:00
|
|
|
+ = map_.find(ix);
|
2013-02-06 16:01:57 -08:00
|
|
|
+ if (it == map_.end()) {
|
|
|
|
+ *have = false;
|
|
|
|
+ return ValueType();
|
|
|
|
+ } else {
|
|
|
|
+ *have = true;
|
|
|
|
+ return it->second;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Lookup 'ix' in the map, and return zero if it is not present.
|
2013-02-07 09:56:27 -08:00
|
|
|
+ ValueType get(const UniqueString* ix) const {
|
|
|
|
+ ++n_gets_;
|
2013-02-06 16:01:57 -08:00
|
|
|
+ bool found;
|
|
|
|
+ ValueType v = get(&found, ix);
|
|
|
|
+ return found ? v : ValueType();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Find out whether 'ix' is in the map.
|
2013-02-07 09:56:27 -08:00
|
|
|
+ bool have(const UniqueString* ix) const {
|
|
|
|
+ ++n_gets_;
|
2013-02-06 16:01:57 -08:00
|
|
|
+ bool found;
|
|
|
|
+ (void)get(&found, ix);
|
|
|
|
+ return found;
|
|
|
|
+ }
|
|
|
|
+
|
2013-02-07 09:56:27 -08:00
|
|
|
+ // Copy the contents to a std::map, generally for testing.
|
|
|
|
+ void copy_to_map(std::map<const UniqueString*, ValueType>* m) const {
|
|
|
|
+ m->clear();
|
|
|
|
+ int i;
|
|
|
|
+ for (i = 0; i < n_fixed_; ++i) {
|
|
|
|
+ (*m)[fixed_keys_[i]] = fixed_vals_[i];
|
|
|
|
+ }
|
|
|
|
+ m->insert(map_.begin(), map_.end());
|
|
|
|
+ }
|
|
|
|
+
|
2013-02-06 16:01:57 -08:00
|
|
|
+ // Note that users of this class rely on having also a sane
|
|
|
|
+ // assignment operator. The default one is OK, though.
|
|
|
|
+ // AFAICT there are no uses of the copy constructor, but if
|
|
|
|
+ // there were, the default one would also suffice.
|
|
|
|
+
|
|
|
|
+ private:
|
2013-02-07 09:56:27 -08:00
|
|
|
+ // Quick (hopefully) cache
|
2013-02-06 16:01:57 -08:00
|
|
|
+ const UniqueString* fixed_keys_[N_FIXED];
|
|
|
|
+ ValueType fixed_vals_[N_FIXED];
|
2013-02-07 09:56:27 -08:00
|
|
|
+ int n_fixed_; // 0 .. N_FIXED inclusive
|
2013-02-06 16:01:57 -08:00
|
|
|
+ // Fallback storage when the cache is filled
|
|
|
|
+ std::map<const UniqueString*, ValueType> map_;
|
|
|
|
+
|
2013-02-07 09:56:27 -08:00
|
|
|
+ // For tracking usage stats.
|
2013-02-06 16:01:57 -08:00
|
|
|
+ mutable int n_sets_, n_gets_, n_clears_;
|
|
|
|
+};
|
|
|
|
+
|
2013-02-07 09:56:27 -08:00
|
|
|
} // namespace google_breakpad
|
|
|
|
|
|
|
|
#endif // COMMON_UNIQUE_STRING_H_
|
2013-02-06 16:01:57 -08:00
|
|
|
diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
|
|
|
|
--- a/src/processor/basic_source_line_resolver_unittest.cc
|
|
|
|
+++ b/src/processor/basic_source_line_resolver_unittest.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -29,6 +29,7 @@
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
+#include <map>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "breakpad_googletest_includes.h"
|
|
|
|
@@ -52,6 +53,7 @@
|
|
|
|
using google_breakpad::MemoryRegion;
|
|
|
|
using google_breakpad::StackFrame;
|
|
|
|
using google_breakpad::ToUniqueString;
|
|
|
|
+using google_breakpad::UniqueString;
|
|
|
|
using google_breakpad::WindowsFrameInfo;
|
|
|
|
using google_breakpad::linked_ptr;
|
|
|
|
using google_breakpad::scoped_ptr;
|
|
|
|
@@ -118,9 +120,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// ".cfa".
|
|
|
|
static bool VerifyRegisters(
|
|
|
|
const char *file, int line,
|
2013-02-07 09:56:27 -08:00
|
|
|
- const CFIFrameInfo::RegisterValueMap<u_int32_t> &expected,
|
|
|
|
- const CFIFrameInfo::RegisterValueMap<u_int32_t> &actual) {
|
2013-02-06 16:01:57 -08:00
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::const_iterator a;
|
2013-02-07 09:56:27 -08:00
|
|
|
+ const std::map<const UniqueString*, u_int32_t> &expected,
|
|
|
|
+ const CFIFrameInfo::RegisterValueMap<u_int32_t> &actual_regmap) {
|
|
|
|
+ std::map<const UniqueString*, u_int32_t> actual;
|
|
|
|
+ actual_regmap.copy_to_map(&actual);
|
|
|
|
+
|
|
|
|
+ std::map<const UniqueString*, u_int32_t>::const_iterator a;
|
|
|
|
a = actual.find(ustr__ZDcfa());
|
|
|
|
if (a == actual.end())
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -128,7 +133,7 @@
|
|
|
|
if (a == actual.end())
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
|
|
|
for (a = actual.begin(); a != actual.end(); a++) {
|
2013-02-07 09:56:27 -08:00
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::const_iterator e =
|
|
|
|
+ std::map<const UniqueString*, u_int32_t>::const_iterator e =
|
2013-02-06 16:01:57 -08:00
|
|
|
expected.find(a->first);
|
|
|
|
if (e == expected.end()) {
|
|
|
|
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -263,7 +268,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
CFIFrameInfo::RegisterValueMap<u_int32_t> current_registers;
|
|
|
|
CFIFrameInfo::RegisterValueMap<u_int32_t> caller_registers;
|
2013-02-07 09:56:27 -08:00
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t> expected_caller_registers;
|
|
|
|
+ std::map<const UniqueString*, u_int32_t> expected_caller_registers;
|
2013-02-06 16:01:57 -08:00
|
|
|
MockMemoryRegion memory;
|
|
|
|
|
|
|
|
// Regardless of which instruction evaluation takes place at, it
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -278,11 +283,11 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
frame.instruction = 0x3d40;
|
|
|
|
frame.module = &module1;
|
|
|
|
current_registers.clear();
|
|
|
|
- current_registers[ustr__ZSesp()] = 0x10018;
|
|
|
|
- current_registers[ustr__ZSebp()] = 0x10038;
|
|
|
|
- current_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
|
|
- current_registers[ustr__ZSesi()] = 0x878f7524;
|
|
|
|
- current_registers[ustr__ZSedi()] = 0x6312f9a5;
|
|
|
|
+ current_registers.set(ustr__ZSesp(), 0x10018);
|
|
|
|
+ current_registers.set(ustr__ZSebp(), 0x10038);
|
|
|
|
+ current_registers.set(ustr__ZSebx(), 0x98ecadc3);
|
|
|
|
+ current_registers.set(ustr__ZSesi(), 0x878f7524);
|
|
|
|
+ current_registers.set(ustr__ZSedi(), 0x6312f9a5);
|
|
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -292,7 +297,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers));
|
|
|
|
|
|
|
|
frame.instruction = 0x3d41;
|
|
|
|
- current_registers[ustr__ZSesp()] = 0x10014;
|
|
|
|
+ current_registers.set(ustr__ZSesp(), 0x10014);
|
|
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -302,7 +307,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers));
|
|
|
|
|
|
|
|
frame.instruction = 0x3d43;
|
|
|
|
- current_registers[ustr__ZSebp()] = 0x10014;
|
|
|
|
+ current_registers.set(ustr__ZSebp(), 0x10014);
|
|
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -312,7 +317,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers);
|
|
|
|
|
|
|
|
frame.instruction = 0x3d54;
|
|
|
|
- current_registers[ustr__ZSebx()] = 0x6864f054U;
|
|
|
|
+ current_registers.set(ustr__ZSebx(), 0x6864f054U);
|
|
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -322,7 +327,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers);
|
|
|
|
|
|
|
|
frame.instruction = 0x3d5a;
|
|
|
|
- current_registers[ustr__ZSesi()] = 0x6285f79aU;
|
|
|
|
+ current_registers.set(ustr__ZSesi(), 0x6285f79aU);
|
|
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -332,7 +337,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers);
|
|
|
|
|
|
|
|
frame.instruction = 0x3d84;
|
|
|
|
- current_registers[ustr__ZSedi()] = 0x64061449U;
|
|
|
|
+ current_registers.set(ustr__ZSedi(), 0x64061449U);
|
|
|
|
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
|
|
diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-inl.h
|
|
|
|
--- a/src/processor/cfi_frame_info-inl.h
|
|
|
|
+++ b/src/processor/cfi_frame_info-inl.h
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -40,30 +40,29 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
namespace google_breakpad {
|
|
|
|
|
|
|
|
-template <typename RegisterType, class RawContextType>
|
|
|
|
-bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters(
|
|
|
|
+template <typename RegisterValueType, class RawContextType>
|
|
|
|
+bool SimpleCFIWalker<RegisterValueType, RawContextType>::FindCallerRegisters(
|
|
|
|
const MemoryRegion &memory,
|
|
|
|
const CFIFrameInfo &cfi_frame_info,
|
|
|
|
const RawContextType &callee_context,
|
|
|
|
int callee_validity,
|
|
|
|
RawContextType *caller_context,
|
|
|
|
int *caller_validity) const {
|
|
|
|
- typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap;
|
|
|
|
+ typedef CFIFrameInfo::RegisterValueMap<RegisterValueType> ValueMap;
|
|
|
|
ValueMap callee_registers;
|
|
|
|
ValueMap caller_registers;
|
|
|
|
- // Just for brevity.
|
|
|
|
- typename ValueMap::const_iterator caller_none = caller_registers.end();
|
|
|
|
|
|
|
|
// Populate callee_registers with register values from callee_context.
|
|
|
|
for (size_t i = 0; i < map_size_; i++) {
|
|
|
|
const RegisterSet &r = register_map_[i];
|
|
|
|
if (callee_validity & r.validity_flag)
|
|
|
|
- callee_registers[r.name] = callee_context.*r.context_member;
|
|
|
|
+ callee_registers.set(r.name, callee_context.*r.context_member);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply the rules, and see what register values they yield.
|
|
|
|
- if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory,
|
|
|
|
- &caller_registers))
|
|
|
|
+ if (!cfi_frame_info
|
|
|
|
+ .FindCallerRegs<RegisterValueType>(callee_registers, memory,
|
|
|
|
+ &caller_registers))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Populate *caller_context with the values the rules placed in
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -72,12 +71,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
*caller_validity = 0;
|
|
|
|
for (size_t i = 0; i < map_size_; i++) {
|
|
|
|
const RegisterSet &r = register_map_[i];
|
|
|
|
- typename ValueMap::const_iterator caller_entry;
|
|
|
|
|
|
|
|
// Did the rules provide a value for this register by its name?
|
|
|
|
- caller_entry = caller_registers.find(r.name);
|
|
|
|
- if (caller_entry != caller_none) {
|
|
|
|
- caller_context->*r.context_member = caller_entry->second;
|
|
|
|
+ bool found = false;
|
|
|
|
+ RegisterValueType v = caller_registers.get(&found, r.name);
|
|
|
|
+ if (found) {
|
|
|
|
+ caller_context->*r.context_member = v;
|
|
|
|
*caller_validity |= r.validity_flag;
|
|
|
|
continue;
|
|
|
|
}
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -85,9 +84,10 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// Did the rules provide a value for this register under its
|
|
|
|
// alternate name?
|
|
|
|
if (r.alternate_name) {
|
|
|
|
- caller_entry = caller_registers.find(r.alternate_name);
|
|
|
|
- if (caller_entry != caller_none) {
|
|
|
|
- caller_context->*r.context_member = caller_entry->second;
|
|
|
|
+ found = false;
|
|
|
|
+ v = caller_registers.get(&found, r.alternate_name);
|
|
|
|
+ if (found) {
|
|
|
|
+ caller_context->*r.context_member = v;
|
|
|
|
*caller_validity |= r.validity_flag;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
|
|
|
|
--- a/src/processor/cfi_frame_info.cc
|
|
|
|
+++ b/src/processor/cfi_frame_info.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -67,7 +67,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// Then, compute the return address.
|
|
|
|
V ra;
|
|
|
|
working = registers;
|
|
|
|
- working[ustr__ZDcfa()] = cfa;
|
|
|
|
+ working.set(ustr__ZDcfa(), cfa);
|
|
|
|
if (!evaluator.EvaluateForValue(ra_rule_, &ra))
|
|
|
|
return false;
|
|
|
|
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -76,14 +76,14 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
it != register_rules_.end(); it++) {
|
|
|
|
V value;
|
|
|
|
working = registers;
|
|
|
|
- working[ustr__ZDcfa()] = cfa;
|
|
|
|
+ working.set(ustr__ZDcfa(), cfa);
|
|
|
|
if (!evaluator.EvaluateForValue(it->second, &value))
|
|
|
|
return false;
|
|
|
|
- (*caller_registers)[it->first] = value;
|
|
|
|
+ caller_registers->set(it->first, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (*caller_registers)[ustr__ZDra()] = ra;
|
|
|
|
- (*caller_registers)[ustr__ZDcfa()] = cfa;
|
|
|
|
+ caller_registers->set(ustr__ZDra(), ra);
|
|
|
|
+ caller_registers->set(ustr__ZDcfa(), cfa);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
|
|
|
|
--- a/src/processor/cfi_frame_info.h
|
|
|
|
+++ b/src/processor/cfi_frame_info.h
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -69,7 +69,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
public:
|
|
|
|
// A map from register names onto values.
|
|
|
|
template<typename ValueType> class RegisterValueMap:
|
|
|
|
- public map<const UniqueString*, ValueType> { };
|
|
|
|
+ public UniqueStringMap<ValueType> { };
|
|
|
|
|
|
|
|
// Set the expression for computing a call frame address, return
|
|
|
|
// address, or register's value. At least the CFA rule and the RA
|
|
|
|
diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
|
|
|
|
--- a/src/processor/cfi_frame_info_unittest.cc
|
|
|
|
+++ b/src/processor/cfi_frame_info_unittest.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -116,9 +116,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
cfi.SetRARule(Module::Expr("5870666104170902211"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(2U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(330903416631436410ULL, caller_registers[ustr__ZDcfa()]);
|
|
|
|
- ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
|
|
|
|
+ ASSERT_EQ(330903416631436410ULL, caller_registers.get(ustr__ZDcfa()));
|
|
|
|
+ ASSERT_EQ(5870666104170902211ULL, caller_registers.get(ustr__ZDra()));
|
|
|
|
|
|
|
|
ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
|
|
|
|
cfi.Serialize());
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -141,13 +140,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(6U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(7664691U, caller_registers[ustr__ZDcfa()]);
|
|
|
|
- ASSERT_EQ(107469446U, caller_registers[ustr__ZDra()]);
|
|
|
|
- ASSERT_EQ(416732599139967ULL, caller_registers[reg1]);
|
|
|
|
- ASSERT_EQ(31740999U, caller_registers[reg2]);
|
|
|
|
- ASSERT_EQ(-22136316ULL, caller_registers[reg3]);
|
|
|
|
- ASSERT_EQ(12U, caller_registers[reg4]);
|
|
|
|
+ ASSERT_EQ(7664691U, caller_registers.get(ustr__ZDcfa()));
|
|
|
|
+ ASSERT_EQ(107469446U, caller_registers.get(ustr__ZDra()));
|
|
|
|
+ ASSERT_EQ(416732599139967ULL, caller_registers.get(reg1));
|
|
|
|
+ ASSERT_EQ(31740999U, caller_registers.get(reg2));
|
|
|
|
+ ASSERT_EQ(-22136316ULL, caller_registers.get(reg3));
|
|
|
|
+ ASSERT_EQ(12U, caller_registers.get(reg4));
|
|
|
|
ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
|
|
|
|
".ra: .cfa 99804755 + "
|
|
|
|
"pubvexingfjordschmaltzy: .cfa 29801007 - "
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -165,9 +163,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
cfi.SetCFARule(Module::Expr("2828089117179001"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(2U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(2828089117179001ULL, caller_registers[ustr__ZDcfa()]);
|
|
|
|
- ASSERT_EQ(5870666104170902211ULL, caller_registers[ustr__ZDra()]);
|
|
|
|
+ ASSERT_EQ(2828089117179001ULL, caller_registers.get(ustr__ZDcfa()));
|
|
|
|
+ ASSERT_EQ(5870666104170902211ULL, caller_registers.get(ustr__ZDra()));
|
|
|
|
ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
|
|
|
|
cfi.Serialize());
|
|
|
|
}
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -201,15 +198,14 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
2013-02-07 09:56:27 -08:00
|
|
|
const UniqueString* reg1 = ToUniqueString(".baraminology");
|
|
|
|
const UniqueString* reg2 = ToUniqueString(".ornithorhynchus");
|
2013-02-06 16:01:57 -08:00
|
|
|
- registers[reg1] = 0x06a7bc63e4f13893ULL;
|
|
|
|
- registers[reg2] = 0x5e0bf850bafce9d2ULL;
|
|
|
|
+ registers.set(reg1, 0x06a7bc63e4f13893ULL);
|
|
|
|
+ registers.set(reg2, 0x5e0bf850bafce9d2ULL);
|
|
|
|
cfi.SetCFARule(Module::Expr(".baraminology .ornithorhynchus +"));
|
|
|
|
cfi.SetRARule(Module::Expr("0"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(2U, caller_registers.size());
|
|
|
|
ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
|
|
|
|
- caller_registers[ustr__ZDcfa()]);
|
|
|
|
+ caller_registers.get(ustr__ZDcfa()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// .cfa should be in scope in the return address expression.
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -220,8 +216,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
cfi.SetRARule(Module::Expr(".cfa"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(2U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(48364076U, caller_registers[ustr__ZDra()]);
|
|
|
|
+ ASSERT_EQ(48364076U, caller_registers.get(ustr__ZDra()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// There should be no value for .ra in scope when evaluating the CFA rule.
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -241,12 +236,11 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
cfi.SetCFARule(Module::Expr("10359370"));
|
2013-02-07 09:56:27 -08:00
|
|
|
const UniqueString* reg1 = ToUniqueString("noachian");
|
2013-02-06 16:01:57 -08:00
|
|
|
- registers[reg1] = 0x54dc4a5d8e5eb503ULL;
|
|
|
|
+ registers.set(reg1, 0x54dc4a5d8e5eb503ULL);
|
|
|
|
cfi.SetRARule(Module::Expr(reg1, 0, false));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(2U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[ustr__ZDra()]);
|
|
|
|
+ ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers.get(ustr__ZDra()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// .cfa should be in scope for register rules.
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -259,8 +253,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
cfi.SetRegisterRule(reg1, Module::Expr(".cfa"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(3U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(6515179U, caller_registers[reg1]);
|
|
|
|
+ ASSERT_EQ(6515179U, caller_registers.get(reg1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// The return address should not be in scope for register rules.
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -281,17 +274,16 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
2013-02-07 09:56:27 -08:00
|
|
|
const UniqueString* reg1 = ToUniqueString("$r1");
|
|
|
|
const UniqueString* reg2 = ToUniqueString("$r2");
|
2013-02-06 16:01:57 -08:00
|
|
|
- registers[reg1] = 0x6ed3582c4bedb9adULL;
|
|
|
|
- registers[reg2] = 0xd27d9e742b8df6d0ULL;
|
|
|
|
+ registers.set(reg1, 0x6ed3582c4bedb9adULL);
|
|
|
|
+ registers.set(reg2, 0xd27d9e742b8df6d0ULL);
|
|
|
|
cfi.SetCFARule(Module::Expr("88239303"));
|
|
|
|
cfi.SetRARule(Module::Expr("30503835"));
|
|
|
|
cfi.SetRegisterRule(reg1, Module::Expr("$r1 42175211 = $r2"));
|
|
|
|
cfi.SetRegisterRule(reg2, Module::Expr("$r2 21357221 = $r1"));
|
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(4U, caller_registers.size());
|
|
|
|
- ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers[reg1]);
|
|
|
|
- ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers[reg2]);
|
|
|
|
+ ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers.get(reg1));
|
|
|
|
+ ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers.get(reg2));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Each rule's temporaries are separate.
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -445,12 +437,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
TEST_F(ParseHandler, CFARARule) {
|
|
|
|
handler.CFARule("reg-for-cfa");
|
|
|
|
handler.RARule("reg-for-ra");
|
2013-02-07 09:56:27 -08:00
|
|
|
- registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
|
|
|
|
- registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
|
|
|
|
+ registers.set(ToUniqueString("reg-for-cfa"), 0x268a9a4a3821a797ULL);
|
|
|
|
+ registers.set(ToUniqueString("reg-for-ra"), 0x6301b475b8b91c02ULL);
|
2013-02-06 16:01:57 -08:00
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
|
|
|
|
- ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
|
|
|
|
+ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers.get(ustr__ZDcfa()));
|
|
|
|
+ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers.get(ustr__ZDra()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ParseHandler, RegisterRules) {
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -458,16 +450,16 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
handler.RARule("reg-for-ra");
|
2013-02-07 09:56:27 -08:00
|
|
|
handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1");
|
|
|
|
handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2");
|
|
|
|
- registers[ToUniqueString("reg-for-cfa")] = 0x268a9a4a3821a797ULL;
|
|
|
|
- registers[ToUniqueString("reg-for-ra")] = 0x6301b475b8b91c02ULL;
|
|
|
|
- registers[ToUniqueString("reg-for-reg1")] = 0x06cde8e2ff062481ULL;
|
|
|
|
- registers[ToUniqueString("reg-for-reg2")] = 0xff0c4f76403173e2ULL;
|
|
|
|
+ registers.set(ToUniqueString("reg-for-cfa"), 0x268a9a4a3821a797ULL);
|
|
|
|
+ registers.set(ToUniqueString("reg-for-ra"), 0x6301b475b8b91c02ULL);
|
|
|
|
+ registers.set(ToUniqueString("reg-for-reg1"), 0x06cde8e2ff062481ULL);
|
|
|
|
+ registers.set(ToUniqueString("reg-for-reg2"), 0xff0c4f76403173e2ULL);
|
2013-02-06 16:01:57 -08:00
|
|
|
ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
|
|
|
|
&caller_registers));
|
|
|
|
- ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[ustr__ZDcfa()]);
|
|
|
|
- ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[ustr__ZDra()]);
|
2013-02-07 09:56:27 -08:00
|
|
|
- ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers[ToUniqueString("reg1")]);
|
|
|
|
- ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers[ToUniqueString("reg2")]);
|
2013-02-06 16:01:57 -08:00
|
|
|
+ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers.get(ustr__ZDcfa()));
|
|
|
|
+ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers.get(ustr__ZDra()));
|
2013-02-07 09:56:27 -08:00
|
|
|
+ ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers.get(ToUniqueString("reg1")));
|
|
|
|
+ ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers.get(ToUniqueString("reg2")));
|
2013-02-06 16:01:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct SimpleCFIWalkerFixture {
|
|
|
|
diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
|
|
|
|
--- a/src/processor/fast_source_line_resolver_unittest.cc
|
|
|
|
+++ b/src/processor/fast_source_line_resolver_unittest.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -64,6 +64,7 @@
|
|
|
|
using google_breakpad::MemoryRegion;
|
|
|
|
using google_breakpad::StackFrame;
|
|
|
|
using google_breakpad::ToUniqueString;
|
|
|
|
+using google_breakpad::UniqueString;
|
|
|
|
using google_breakpad::WindowsFrameInfo;
|
|
|
|
using google_breakpad::linked_ptr;
|
|
|
|
using google_breakpad::scoped_ptr;
|
|
|
|
@@ -130,9 +131,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// ".cfa".
|
|
|
|
static bool VerifyRegisters(
|
|
|
|
const char *file, int line,
|
2013-02-07 09:56:27 -08:00
|
|
|
- const CFIFrameInfo::RegisterValueMap<u_int32_t> &expected,
|
|
|
|
- const CFIFrameInfo::RegisterValueMap<u_int32_t> &actual) {
|
2013-02-06 16:01:57 -08:00
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::const_iterator a;
|
2013-02-07 09:56:27 -08:00
|
|
|
+ const std::map<const UniqueString*, u_int32_t> &expected,
|
|
|
|
+ const CFIFrameInfo::RegisterValueMap<u_int32_t> &actual_regmap) {
|
|
|
|
+ std::map<const UniqueString*, u_int32_t> actual;
|
|
|
|
+ actual_regmap.copy_to_map(&actual);
|
|
|
|
+
|
|
|
|
+ std::map<const UniqueString*, u_int32_t>::const_iterator a;
|
|
|
|
a = actual.find(ustr__ZDcfa());
|
|
|
|
if (a == actual.end())
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -140,7 +144,7 @@
|
|
|
|
if (a == actual.end())
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
|
|
|
for (a = actual.begin(); a != actual.end(); a++) {
|
2013-02-07 09:56:27 -08:00
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::const_iterator e =
|
|
|
|
+ std::map<const UniqueString*, u_int32_t>::const_iterator e =
|
2013-02-06 16:01:57 -08:00
|
|
|
expected.find(a->first);
|
|
|
|
if (e == expected.end()) {
|
|
|
|
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -291,13 +295,14 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
CFIFrameInfo::RegisterValueMap<u_int32_t> current_registers;
|
|
|
|
CFIFrameInfo::RegisterValueMap<u_int32_t> caller_registers;
|
2013-02-07 09:56:27 -08:00
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t> expected_caller_registers;
|
|
|
|
+ std::map<const UniqueString*, u_int32_t> expected_caller_registers;
|
2013-02-06 16:01:57 -08:00
|
|
|
MockMemoryRegion memory;
|
|
|
|
|
|
|
|
// Regardless of which instruction evaluation takes place at, it
|
|
|
|
// should produce the same values for the caller's registers.
|
2013-02-07 09:56:27 -08:00
|
|
|
+ // should produce the same values for the caller's registers.
|
|
|
|
expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
|
2013-02-06 16:01:57 -08:00
|
|
|
- expected_caller_registers[ustr__ZDra()] = 0xf6438648;
|
2013-02-07 09:56:27 -08:00
|
|
|
+ expected_caller_registers[ustr__ZDra()] = 0xf6438648;
|
|
|
|
expected_caller_registers[ustr__ZSebp()] = 0x10038;
|
|
|
|
expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
|
|
expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
|
|
|
|
@@ -306,11 +311,11 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
frame.instruction = 0x3d40;
|
|
|
|
frame.module = &module1;
|
|
|
|
current_registers.clear();
|
|
|
|
- current_registers[ustr__ZSesp()] = 0x10018;
|
|
|
|
- current_registers[ustr__ZSebp()] = 0x10038;
|
|
|
|
- current_registers[ustr__ZSebx()] = 0x98ecadc3;
|
|
|
|
- current_registers[ustr__ZSesi()] = 0x878f7524;
|
|
|
|
- current_registers[ustr__ZSedi()] = 0x6312f9a5;
|
|
|
|
+ current_registers.set(ustr__ZSesp(), 0x10018);
|
|
|
|
+ current_registers.set(ustr__ZSebp(), 0x10038);
|
|
|
|
+ current_registers.set(ustr__ZSebx(), 0x98ecadc3);
|
|
|
|
+ current_registers.set(ustr__ZSesi(), 0x878f7524);
|
|
|
|
+ current_registers.set(ustr__ZSedi(), 0x6312f9a5);
|
|
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -320,7 +325,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers));
|
|
|
|
|
|
|
|
frame.instruction = 0x3d41;
|
|
|
|
- current_registers[ustr__ZSesp()] = 0x10014;
|
|
|
|
+ current_registers.set(ustr__ZSesp(), 0x10014);
|
|
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -330,7 +335,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers));
|
|
|
|
|
|
|
|
frame.instruction = 0x3d43;
|
|
|
|
- current_registers[ustr__ZSebp()] = 0x10014;
|
|
|
|
+ current_registers.set(ustr__ZSebp(), 0x10014);
|
|
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -340,7 +345,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers);
|
|
|
|
|
|
|
|
frame.instruction = 0x3d54;
|
|
|
|
- current_registers[ustr__ZSebx()] = 0x6864f054U;
|
|
|
|
+ current_registers.set(ustr__ZSebx(), 0x6864f054U);
|
|
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -350,7 +355,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers);
|
|
|
|
|
|
|
|
frame.instruction = 0x3d5a;
|
|
|
|
- current_registers[ustr__ZSesi()] = 0x6285f79aU;
|
|
|
|
+ current_registers.set(ustr__ZSesi(), 0x6285f79aU);
|
|
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -360,7 +365,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
expected_caller_registers, caller_registers);
|
|
|
|
|
|
|
|
frame.instruction = 0x3d84;
|
|
|
|
- current_registers[ustr__ZSedi()] = 0x64061449U;
|
|
|
|
+ current_registers.set(ustr__ZSedi(), 0x64061449U);
|
|
|
|
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get());
|
|
|
|
ASSERT_TRUE(cfi_frame_info.get()
|
|
|
|
diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h
|
|
|
|
--- a/src/processor/postfix_evaluator-inl.h
|
|
|
|
+++ b/src/processor/postfix_evaluator-inl.h
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -190,9 +190,9 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (*dictionary_)[identifier] = value;
|
|
|
|
+ dictionary_->set(identifier, value);
|
|
|
|
if (assigned)
|
|
|
|
- (*assigned)[identifier] = true;
|
|
|
|
+ assigned->set(identifier, true);
|
|
|
|
} else {
|
2013-02-07 09:56:27 -08:00
|
|
|
// Push it onto the stack as-is, but first convert it either to a
|
2013-02-06 16:01:57 -08:00
|
|
|
// ValueType (if a literal) or to a UniqueString* (if an identifier).
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -305,18 +305,18 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
case Module::kExprSimple:
|
|
|
|
case Module::kExprSimpleMem: {
|
|
|
|
// Look up the base value
|
|
|
|
- typename DictionaryType::const_iterator iterator
|
|
|
|
- = dictionary_->find(expr.ident_);
|
|
|
|
- if (iterator == dictionary_->end()) {
|
|
|
|
+ bool found = false;
|
|
|
|
+ ValueType v = dictionary_->get(&found, expr.ident_);
|
|
|
|
+ if (!found) {
|
|
|
|
// The identifier wasn't found in the dictionary. Don't imply any
|
|
|
|
// default value, just fail.
|
|
|
|
- BPLOG(INFO) << "Identifier " << expr.ident_
|
2013-02-07 09:56:27 -08:00
|
|
|
+ BPLOG(INFO) << "Identifier " << FromUniqueString(expr.ident_)
|
2013-02-06 16:01:57 -08:00
|
|
|
<< " not in dictionary (kExprSimple{Mem})";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Form the sum
|
|
|
|
- ValueType sum = iterator->second + (int64_t)expr.offset_;
|
|
|
|
+ ValueType sum = v + (int64_t)expr.offset_;
|
|
|
|
|
|
|
|
// and dereference if necessary
|
|
|
|
if (expr.how_ == Module::kExprSimpleMem) {
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -373,9 +373,9 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
} else { // result == POP_RESULT_IDENTIFIER
|
|
|
|
// There was an identifier at the top of the stack. Resolve it to a
|
|
|
|
// value by looking it up in the dictionary.
|
|
|
|
- typename DictionaryType::const_iterator iterator =
|
|
|
|
- dictionary_->find(token);
|
|
|
|
- if (iterator == dictionary_->end()) {
|
|
|
|
+ bool found = false;
|
|
|
|
+ ValueType v = dictionary_->get(&found, token);
|
|
|
|
+ if (!found) {
|
|
|
|
// The identifier wasn't found in the dictionary. Don't imply any
|
|
|
|
// default value, just fail.
|
2013-02-07 09:56:27 -08:00
|
|
|
BPLOG(INFO) << "Identifier " << FromUniqueString(token)
|
|
|
|
@@ -383,7 +383,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
- *value = iterator->second;
|
|
|
|
+ *value = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
|
|
|
|
--- a/src/processor/postfix_evaluator.h
|
|
|
|
+++ b/src/processor/postfix_evaluator.h
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -98,8 +98,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
template<typename ValueType>
|
|
|
|
class PostfixEvaluator {
|
|
|
|
public:
|
|
|
|
- typedef map<const UniqueString*, ValueType> DictionaryType;
|
|
|
|
- typedef map<const UniqueString*, bool> DictionaryValidityType;
|
|
|
|
+ typedef UniqueStringMap<ValueType> DictionaryType;
|
|
|
|
+ typedef UniqueStringMap<bool> DictionaryValidityType;
|
|
|
|
|
|
|
|
// Create a PostfixEvaluator object that may be used (with Evaluate) on
|
|
|
|
// one or more expressions. PostfixEvaluator does not take ownership of
|
|
|
|
diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
|
|
|
|
--- a/src/processor/postfix_evaluator_unittest.cc
|
|
|
|
+++ b/src/processor/postfix_evaluator_unittest.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -183,12 +183,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// instead of a real stack snapshot, but the program strings are real and
|
|
|
|
// the implementation doesn't know or care that the data is not real.
|
|
|
|
PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
|
|
|
|
- dictionary_1[ustr__ZSebp()] = 0xbfff0010;
|
|
|
|
- dictionary_1[ustr__ZSeip()] = 0x10000000;
|
|
|
|
- dictionary_1[ustr__ZSesp()] = 0xbfff0000;
|
|
|
|
- dictionary_1[ustr__ZDcbSavedRegs()] = 4;
|
|
|
|
- dictionary_1[ustr__ZDcbParams()] = 4;
|
|
|
|
- dictionary_1[ustr__ZDraSearchStart()] = 0xbfff0020;
|
|
|
|
+ dictionary_1.set(ustr__ZSebp(), 0xbfff0010);
|
|
|
|
+ dictionary_1.set(ustr__ZSeip(), 0x10000000);
|
|
|
|
+ dictionary_1.set(ustr__ZSesp(), 0xbfff0000);
|
|
|
|
+ dictionary_1.set(ustr__ZDcbSavedRegs(), 4);
|
|
|
|
+ dictionary_1.set(ustr__ZDcbParams(), 4);
|
|
|
|
+ dictionary_1.set(ustr__ZDraSearchStart(), 0xbfff0020);
|
|
|
|
const EvaluateTest evaluate_tests_1[] = {
|
|
|
|
{ "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
|
|
|
|
"$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -278,12 +278,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
const UniqueString* identifier = validate_iterator->first;
|
|
|
|
unsigned int expected_value = validate_iterator->second;
|
|
|
|
|
|
|
|
- map<const UniqueString*, unsigned int>::const_iterator
|
|
|
|
- dictionary_iterator =
|
|
|
|
- evaluate_test_set->dictionary->find(identifier);
|
|
|
|
-
|
|
|
|
// The identifier must exist in the dictionary.
|
|
|
|
- if (dictionary_iterator == evaluate_test_set->dictionary->end()) {
|
|
|
|
+ if (!evaluate_test_set->dictionary->have(identifier)) {
|
|
|
|
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
|
|
|
|
"validate identifier \"%s\", "
|
|
|
|
"expected %d, observed not found\n",
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -293,7 +289,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// The value in the dictionary must be the same as the expected value.
|
|
|
|
- unsigned int observed_value = dictionary_iterator->second;
|
|
|
|
+ unsigned int observed_value =
|
|
|
|
+ evaluate_test_set->dictionary->get(identifier);
|
|
|
|
if (expected_value != observed_value) {
|
|
|
|
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
|
|
|
|
"validate identifier \"%s\", "
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -307,10 +304,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// variable. It must not have been assigned if it was a constant.
|
2013-02-07 09:56:27 -08:00
|
|
|
bool expected_assigned = FromUniqueString(identifier)[0] == '$';
|
2013-02-06 16:01:57 -08:00
|
|
|
bool observed_assigned = false;
|
|
|
|
- PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator
|
|
|
|
- iterator_assigned = assigned.find(identifier);
|
|
|
|
- if (iterator_assigned != assigned.end()) {
|
|
|
|
- observed_assigned = iterator_assigned->second;
|
|
|
|
+ if (assigned.have(identifier)) {
|
|
|
|
+ observed_assigned = assigned.get(identifier);
|
|
|
|
}
|
|
|
|
if (expected_assigned != observed_assigned) {
|
|
|
|
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -326,12 +321,12 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
// EvaluateForValue tests.
|
|
|
|
PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
|
|
|
|
- dictionary_2[ustr__ZSebp()] = 0xbfff0010;
|
|
|
|
- dictionary_2[ustr__ZSeip()] = 0x10000000;
|
|
|
|
- dictionary_2[ustr__ZSesp()] = 0xbfff0000;
|
|
|
|
- dictionary_2[ustr__ZDcbSavedRegs()] = 4;
|
|
|
|
- dictionary_2[ustr__ZDcbParams()] = 4;
|
|
|
|
- dictionary_2[ustr__ZDraSearchStart()] = 0xbfff0020;
|
|
|
|
+ dictionary_2.set(ustr__ZSebp(), 0xbfff0010);
|
|
|
|
+ dictionary_2.set(ustr__ZSeip(), 0x10000000);
|
|
|
|
+ dictionary_2.set(ustr__ZSesp(), 0xbfff0000);
|
|
|
|
+ dictionary_2.set(ustr__ZDcbSavedRegs(), 4);
|
|
|
|
+ dictionary_2.set(ustr__ZDcbParams(), 4);
|
|
|
|
+ dictionary_2.set(ustr__ZDraSearchStart(), 0xbfff0020);
|
|
|
|
const EvaluateForValueTest evaluate_for_value_tests_2[] = {
|
|
|
|
{ "28907223", true, 28907223 }, // simple constant
|
|
|
|
{ "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -375,12 +370,14 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-07 09:56:27 -08:00
|
|
|
+ map<const UniqueString*, unsigned int> dictionary_2_map;
|
|
|
|
+ dictionary_2.copy_to_map(&dictionary_2_map);
|
2013-02-06 16:01:57 -08:00
|
|
|
for (map<const UniqueString*, unsigned int>::iterator v =
|
|
|
|
validate_data_2.begin();
|
|
|
|
v != validate_data_2.end(); v++) {
|
2013-02-07 09:56:27 -08:00
|
|
|
map<const UniqueString*, unsigned int>::iterator a =
|
2013-02-06 16:01:57 -08:00
|
|
|
- dictionary_2.find(v->first);
|
|
|
|
- if (a == dictionary_2.end()) {
|
2013-02-07 09:56:27 -08:00
|
|
|
+ dictionary_2_map.find(v->first);
|
|
|
|
+ if (a == dictionary_2_map.end()) {
|
2013-02-06 16:01:57 -08:00
|
|
|
fprintf(stderr, "FAIL: evaluate for value dictionary check: "
|
|
|
|
"expected dict[\"%s\"] to be 0x%x, but it was unset\n",
|
2013-02-07 09:56:27 -08:00
|
|
|
FromUniqueString(v->first), v->second);
|
|
|
|
@@ -390,16 +387,16 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
"expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
|
2013-02-07 09:56:27 -08:00
|
|
|
FromUniqueString(v->first), v->second, a->second);
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
|
|
|
- }
|
|
|
|
- dictionary_2.erase(a);
|
|
|
|
+ }
|
2013-02-07 09:56:27 -08:00
|
|
|
+ dictionary_2_map.erase(a);
|
2013-02-06 16:01:57 -08:00
|
|
|
}
|
|
|
|
-
|
2013-02-07 09:56:27 -08:00
|
|
|
+
|
2013-02-06 16:01:57 -08:00
|
|
|
map<const UniqueString*, unsigned int>::iterator remaining =
|
2013-02-07 09:56:27 -08:00
|
|
|
- dictionary_2.begin();
|
|
|
|
- if (remaining != dictionary_2.end()) {
|
|
|
|
+ dictionary_2_map.begin();
|
|
|
|
+ if (remaining != dictionary_2_map.end()) {
|
2013-02-06 16:01:57 -08:00
|
|
|
fprintf(stderr, "FAIL: evaluation of test expressions put unexpected "
|
|
|
|
"values in dictionary:\n");
|
2013-02-07 09:56:27 -08:00
|
|
|
- for (; remaining != dictionary_2.end(); remaining++)
|
|
|
|
+ for (; remaining != dictionary_2_map.end(); remaining++)
|
2013-02-06 16:01:57 -08:00
|
|
|
fprintf(stderr, " dict[\"%s\"] == 0x%x\n",
|
2013-02-07 09:56:27 -08:00
|
|
|
FromUniqueString(remaining->first), remaining->second);
|
2013-02-06 16:01:57 -08:00
|
|
|
return false;
|
|
|
|
diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
|
|
|
|
--- a/src/processor/stackwalker_arm.cc
|
|
|
|
+++ b/src/processor/stackwalker_arm.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -102,7 +102,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
CFIFrameInfo::RegisterValueMap<u_int32_t> callee_registers;
|
|
|
|
for (int i = 0; register_names[i]; i++)
|
|
|
|
if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
|
|
|
|
- callee_registers[register_names[i]] = last_frame->context.iregs[i];
|
|
|
|
+ callee_registers.set(register_names[i], last_frame->context.iregs[i]);
|
|
|
|
|
|
|
|
// Use the STACK CFI data to recover the caller's register values.
|
|
|
|
CFIFrameInfo::RegisterValueMap<u_int32_t> caller_registers;
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -113,13 +113,13 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// Construct a new stack frame given the values the CFI recovered.
|
|
|
|
scoped_ptr<StackFrameARM> frame(new StackFrameARM());
|
|
|
|
for (int i = 0; register_names[i]; i++) {
|
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry =
|
|
|
|
- caller_registers.find(register_names[i]);
|
|
|
|
- if (entry != caller_registers.end()) {
|
|
|
|
+ bool found = false;
|
|
|
|
+ u_int32_t v = caller_registers.get(&found, register_names[i]);
|
|
|
|
+ if (found) {
|
|
|
|
// We recovered the value of this register; fill the context with the
|
|
|
|
// value from caller_registers.
|
|
|
|
frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
|
|
|
|
- frame->context.iregs[i] = entry->second;
|
|
|
|
+ frame->context.iregs[i] = v;
|
|
|
|
} else if (4 <= i && i <= 11 && (last_frame->context_validity &
|
|
|
|
StackFrameARM::RegisterValidFlag(i))) {
|
|
|
|
// If the STACK CFI data doesn't mention some callee-saves register, and
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -132,18 +132,18 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
}
|
|
|
|
// If the CFI doesn't recover the PC explicitly, then use .ra.
|
|
|
|
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
|
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry =
|
|
|
|
- caller_registers.find(ustr__ZDra());
|
|
|
|
- if (entry != caller_registers.end()) {
|
|
|
|
+ bool found = false;
|
|
|
|
+ u_int32_t v = caller_registers.get(&found, ustr__ZDra());
|
|
|
|
+ if (found) {
|
|
|
|
if (fp_register_ == -1) {
|
|
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
|
|
|
|
- frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second;
|
|
|
|
+ frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = v;
|
|
|
|
} else {
|
|
|
|
// The CFI updated the link register and not the program counter.
|
|
|
|
// Handle getting the program counter from the link register.
|
|
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
|
|
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_LR;
|
|
|
|
- frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = entry->second;
|
|
|
|
+ frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = v;
|
|
|
|
frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
|
|
|
|
last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
|
|
|
|
}
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -151,11 +151,11 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
}
|
|
|
|
// If the CFI doesn't recover the SP explicitly, then use .cfa.
|
|
|
|
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
|
|
|
|
- CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry =
|
|
|
|
- caller_registers.find(ustr__ZDcfa());
|
|
|
|
- if (entry != caller_registers.end()) {
|
|
|
|
+ bool found = false;
|
|
|
|
+ u_int32_t v = caller_registers.get(&found, ustr__ZDcfa());
|
|
|
|
+ if (found) {
|
|
|
|
frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP;
|
|
|
|
- frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second;
|
|
|
|
+ frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
|
|
|
|
--- a/src/processor/stackwalker_x86.cc
|
|
|
|
+++ b/src/processor/stackwalker_x86.cc
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -199,16 +199,16 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// here.
|
|
|
|
PostfixEvaluator<u_int32_t>::DictionaryType dictionary;
|
|
|
|
// Provide the current register values.
|
|
|
|
- dictionary[ustr__ZSebp()] = last_frame->context.ebp;
|
|
|
|
- dictionary[ustr__ZSesp()] = last_frame->context.esp;
|
|
|
|
+ dictionary.set(ustr__ZSebp(), last_frame->context.ebp);
|
|
|
|
+ dictionary.set(ustr__ZSesp(), last_frame->context.esp);
|
|
|
|
// Provide constants from the debug info for last_frame and its callee.
|
|
|
|
// .cbCalleeParams is a Breakpad extension that allows us to use the
|
|
|
|
// PostfixEvaluator engine when certain types of debugging information
|
|
|
|
// are present without having to write the constants into the program
|
|
|
|
// string as literals.
|
|
|
|
- dictionary[ustr__ZDcbCalleeParams()] = last_frame_callee_parameter_size;
|
|
|
|
- dictionary[ustr__ZDcbSavedRegs()] = last_frame_info->saved_register_size;
|
|
|
|
- dictionary[ustr__ZDcbLocals()] = last_frame_info->local_size;
|
|
|
|
+ dictionary.set(ustr__ZDcbCalleeParams(), last_frame_callee_parameter_size);
|
|
|
|
+ dictionary.set(ustr__ZDcbSavedRegs(), last_frame_info->saved_register_size);
|
|
|
|
+ dictionary.set(ustr__ZDcbLocals(), last_frame_info->local_size);
|
|
|
|
|
|
|
|
u_int32_t raSearchStart = last_frame->context.esp +
|
|
|
|
last_frame_callee_parameter_size +
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -237,10 +237,10 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
// The difference between raSearch and raSearchStart is unknown,
|
|
|
|
// but making them the same seems to work well in practice.
|
|
|
|
- dictionary[ustr__ZDraSearchStart()] = raSearchStart;
|
|
|
|
- dictionary[ustr__ZDraSearch()] = raSearchStart;
|
|
|
|
+ dictionary.set(ustr__ZDraSearchStart(), raSearchStart);
|
|
|
|
+ dictionary.set(ustr__ZDraSearch(), raSearchStart);
|
|
|
|
|
|
|
|
- dictionary[ustr__ZDcbParams()] = last_frame_info->parameter_size;
|
|
|
|
+ dictionary.set(ustr__ZDcbParams(), last_frame_info->parameter_size);
|
|
|
|
|
|
|
|
// Decide what type of program string to use. The program string is in
|
|
|
|
// postfix notation and will be passed to PostfixEvaluator::Evaluate.
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -330,8 +330,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
PostfixEvaluator<u_int32_t>(&dictionary, memory_);
|
|
|
|
PostfixEvaluator<u_int32_t>::DictionaryValidityType dictionary_validity;
|
|
|
|
if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
|
|
|
|
- dictionary_validity.find(ustr__ZSeip()) == dictionary_validity.end() ||
|
|
|
|
- dictionary_validity.find(ustr__ZSesp()) == dictionary_validity.end()) {
|
|
|
|
+ !dictionary_validity.have(ustr__ZSeip()) ||
|
|
|
|
+ !dictionary_validity.have(ustr__ZSesp())) {
|
|
|
|
// Program string evaluation failed. It may be that %eip is not somewhere
|
|
|
|
// with stack frame info, and %ebp is pointing to non-stack memory, so
|
|
|
|
// our evaluation couldn't succeed. We'll scan the stack for a return
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -349,8 +349,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// This seems like a reasonable return address. Since program string
|
|
|
|
// evaluation failed, use it and set %esp to the location above the
|
|
|
|
// one where the return address was found.
|
|
|
|
- dictionary[ustr__ZSeip()] = eip;
|
|
|
|
- dictionary[ustr__ZSesp()] = location + 4;
|
|
|
|
+ dictionary.set(ustr__ZSeip(), eip);
|
|
|
|
+ dictionary.set(ustr__ZSesp(), location + 4);
|
|
|
|
trust = StackFrame::FRAME_TRUST_SCAN;
|
|
|
|
}
|
|
|
|
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -361,7 +361,8 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// However, if program string evaluation resulted in both %eip and
|
|
|
|
// %ebp values of 0, trust that the end of the stack has been
|
|
|
|
// reached and don't scan for anything else.
|
|
|
|
- if (dictionary[ustr__ZSeip()] != 0 || dictionary[ustr__ZSebp()] != 0) {
|
|
|
|
+ if (dictionary.get(ustr__ZSeip()) != 0 ||
|
|
|
|
+ dictionary.get(ustr__ZSebp()) != 0) {
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
// This scan can only be done if a CodeModules object is available, to
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -376,18 +377,18 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
|
|
|
|
// an independent execute privilege on memory pages.
|
|
|
|
|
|
|
|
- u_int32_t eip = dictionary[ustr__ZSeip()];
|
|
|
|
+ u_int32_t eip = dictionary.get(ustr__ZSeip());
|
|
|
|
if (modules_ && !modules_->GetModuleForAddress(eip)) {
|
|
|
|
// The instruction pointer at .raSearchStart was invalid, so start
|
|
|
|
// looking one 32-bit word above that location.
|
|
|
|
- u_int32_t location_start = dictionary[ustr__ZDraSearchStart()] + 4;
|
|
|
|
+ u_int32_t location_start = dictionary.get(ustr__ZDraSearchStart()) + 4;
|
|
|
|
u_int32_t location;
|
|
|
|
if (ScanForReturnAddress(location_start, &location, &eip)) {
|
|
|
|
// This is a better return address that what program string
|
|
|
|
// evaluation found. Use it, and set %esp to the location above the
|
|
|
|
// one where the return address was found.
|
|
|
|
- dictionary[ustr__ZSeip()] = eip;
|
|
|
|
- dictionary[ustr__ZSesp()] = location + 4;
|
|
|
|
+ dictionary.set(ustr__ZSeip(), eip);
|
|
|
|
+ dictionary.set(ustr__ZSesp(), location + 4);
|
|
|
|
offset = location - location_start;
|
|
|
|
trust = StackFrame::FRAME_TRUST_CFI_SCAN;
|
|
|
|
}
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -401,7 +402,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
// stack. The scan is performed from the highest possible address to
|
|
|
|
// the lowest, because the expectation is that the function's prolog
|
|
|
|
// would have saved %ebp early.
|
|
|
|
- u_int32_t ebp = dictionary[ustr__ZSebp()];
|
|
|
|
+ u_int32_t ebp = dictionary.get(ustr__ZSebp());
|
|
|
|
|
|
|
|
// When a scan for return address is used, it is possible to skip one or
|
|
|
|
// more frames (when return address is not in a known module). One
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -425,7 +426,7 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
if (memory_->GetMemoryAtAddress(ebp, &value)) {
|
|
|
|
// The candidate value is a pointer to the same memory region
|
|
|
|
// (the stack). Prefer it as a recovered %ebp result.
|
|
|
|
- dictionary[ustr__ZSebp()] = ebp;
|
|
|
|
+ dictionary.set(ustr__ZSebp(), ebp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-02-07 09:56:27 -08:00
|
|
|
@@ -439,25 +440,25 @@
|
2013-02-06 16:01:57 -08:00
|
|
|
|
|
|
|
frame->trust = trust;
|
|
|
|
frame->context = last_frame->context;
|
|
|
|
- frame->context.eip = dictionary[ustr__ZSeip()];
|
|
|
|
- frame->context.esp = dictionary[ustr__ZSesp()];
|
|
|
|
- frame->context.ebp = dictionary[ustr__ZSebp()];
|
|
|
|
+ frame->context.eip = dictionary.get(ustr__ZSeip());
|
|
|
|
+ frame->context.esp = dictionary.get(ustr__ZSesp());
|
|
|
|
+ frame->context.ebp = dictionary.get(ustr__ZSebp());
|
|
|
|
frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
|
|
|
|
StackFrameX86::CONTEXT_VALID_ESP |
|
|
|
|
StackFrameX86::CONTEXT_VALID_EBP;
|
|
|
|
|
|
|
|
// These are nonvolatile (callee-save) registers, and the program string
|
|
|
|
// may have filled them in.
|
|
|
|
- if (dictionary_validity.find(ustr__ZSebx()) != dictionary_validity.end()) {
|
|
|
|
- frame->context.ebx = dictionary[ustr__ZSebx()];
|
|
|
|
+ if (dictionary_validity.have(ustr__ZSebx())) {
|
|
|
|
+ frame->context.ebx = dictionary.get(ustr__ZSebx());
|
|
|
|
frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX;
|
|
|
|
}
|
|
|
|
- if (dictionary_validity.find(ustr__ZSesi()) != dictionary_validity.end()) {
|
|
|
|
- frame->context.esi = dictionary[ustr__ZSesi()];
|
|
|
|
+ if (dictionary_validity.have(ustr__ZSesi())) {
|
|
|
|
+ frame->context.esi = dictionary.get(ustr__ZSesi());
|
|
|
|
frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI;
|
|
|
|
}
|
|
|
|
- if (dictionary_validity.find(ustr__ZSedi()) != dictionary_validity.end()) {
|
|
|
|
- frame->context.edi = dictionary[ustr__ZSedi()];
|
|
|
|
+ if (dictionary_validity.have(ustr__ZSedi())) {
|
|
|
|
+ frame->context.edi = dictionary.get(ustr__ZSedi());
|
|
|
|
frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
|
|
|
|
}
|
|
|
|
|