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

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

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

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial