PageRenderTime 63ms CodeModel.GetById 11ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/processor/cfi_frame_info_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 545 lines | 396 code | 82 blank | 67 comment | 0 complexity | 310f0c41926d5ea1c244cad48b41e723 MD5 | raw file
  1// Copyright (c) 2010, Google Inc.
  2// All rights reserved.
  3//
  4// Redistribution and use in source and binary forms, with or without
  5// modification, are permitted provided that the following conditions are
  6// met:
  7//
  8//     * Redistributions of source code must retain the above copyright
  9// notice, this list of conditions and the following disclaimer.
 10//     * Redistributions in binary form must reproduce the above
 11// copyright notice, this list of conditions and the following disclaimer
 12// in the documentation and/or other materials provided with the
 13// distribution.
 14//     * Neither the name of Google Inc. nor the names of its
 15// contributors may be used to endorse or promote products derived from
 16// this software without specific prior written permission.
 17//
 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29
 30// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 31
 32// cfi_frame_info_unittest.cc: Unit tests for CFIFrameInfo,
 33// CFIRuleParser, CFIFrameInfoParseHandler, and SimpleCFIWalker.
 34
 35#include <string.h>
 36
 37#include "breakpad_googletest_includes.h"
 38#include "processor/cfi_frame_info.h"
 39#include "google_breakpad/processor/memory_region.h"
 40
 41using google_breakpad::CFIFrameInfo;
 42using google_breakpad::CFIFrameInfoParseHandler;
 43using google_breakpad::CFIRuleParser;
 44using google_breakpad::MemoryRegion;
 45using google_breakpad::SimpleCFIWalker;
 46using std::string;
 47using testing::_;
 48using testing::A;
 49using testing::AtMost;
 50using testing::DoAll;
 51using testing::Return;
 52using testing::SetArgumentPointee;
 53using testing::Test;
 54
 55class MockMemoryRegion: public MemoryRegion {
 56 public:
 57  MOCK_CONST_METHOD0(GetBase, u_int64_t());
 58  MOCK_CONST_METHOD0(GetSize, u_int32_t());
 59  MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(u_int64_t, u_int8_t *));
 60  MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(u_int64_t, u_int16_t *));
 61  MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(u_int64_t, u_int32_t *));
 62  MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(u_int64_t, u_int64_t *));
 63};
 64
 65// Handy definitions for all tests.
 66struct CFIFixture {
 67
 68  // Set up the mock memory object to expect no references.
 69  void ExpectNoMemoryReferences() {
 70    EXPECT_CALL(memory, GetBase()).Times(0);
 71    EXPECT_CALL(memory, GetSize()).Times(0);
 72    EXPECT_CALL(memory, GetMemoryAtAddress(_, A<u_int8_t *>())).Times(0);
 73    EXPECT_CALL(memory, GetMemoryAtAddress(_, A<u_int16_t *>())).Times(0);
 74    EXPECT_CALL(memory, GetMemoryAtAddress(_, A<u_int32_t *>())).Times(0);
 75    EXPECT_CALL(memory, GetMemoryAtAddress(_, A<u_int64_t *>())).Times(0);
 76  }
 77
 78  CFIFrameInfo cfi;
 79  MockMemoryRegion memory;
 80  CFIFrameInfo::RegisterValueMap<u_int64_t> registers, caller_registers;
 81};
 82
 83class Simple: public CFIFixture, public Test { };
 84
 85// FindCallerRegs should fail if no .cfa rule is provided.
 86TEST_F(Simple, NoCFA) {
 87  ExpectNoMemoryReferences();
 88
 89  cfi.SetRARule("0");
 90  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
 91                                             &caller_registers));
 92  ASSERT_EQ(".ra: 0", cfi.Serialize());
 93}
 94
 95// FindCallerRegs should fail if no .ra rule is provided.
 96TEST_F(Simple, NoRA) {
 97  ExpectNoMemoryReferences();
 98
 99  cfi.SetCFARule("0");
100  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
101                                             &caller_registers));
102  ASSERT_EQ(".cfa: 0", cfi.Serialize());
103}
104
105TEST_F(Simple, SetCFAAndRARule) {
106  ExpectNoMemoryReferences();
107
108  cfi.SetCFARule("330903416631436410");
109  cfi.SetRARule("5870666104170902211");
110  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
111                                            &caller_registers));
112  ASSERT_EQ(2U, caller_registers.size());
113  ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]);
114  ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
115
116  ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
117            cfi.Serialize());
118}
119
120TEST_F(Simple, SetManyRules) {
121  ExpectNoMemoryReferences();
122
123  cfi.SetCFARule("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -");
124  cfi.SetRARule(".cfa 99804755 +");
125  cfi.SetRegisterRule("register1", ".cfa 54370437 *");
126  cfi.SetRegisterRule("vodkathumbscrewingly", "24076308 .cfa +");
127  cfi.SetRegisterRule("pubvexingfjordschmaltzy", ".cfa 29801007 -");
128  cfi.SetRegisterRule("uncopyrightables", "92642917 .cfa /");
129  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
130                                            &caller_registers));
131  ASSERT_EQ(6U, caller_registers.size());
132  ASSERT_EQ(7664691U,           caller_registers[".cfa"]);
133  ASSERT_EQ(107469446U,         caller_registers[".ra"]);
134  ASSERT_EQ(416732599139967ULL, caller_registers["register1"]);
135  ASSERT_EQ(31740999U,          caller_registers["vodkathumbscrewingly"]);
136  ASSERT_EQ(-22136316ULL,       caller_registers["pubvexingfjordschmaltzy"]);
137  ASSERT_EQ(12U,                caller_registers["uncopyrightables"]);
138  ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
139            ".ra: .cfa 99804755 + "
140            "pubvexingfjordschmaltzy: .cfa 29801007 - "
141            "register1: .cfa 54370437 * "
142            "uncopyrightables: 92642917 .cfa / "
143            "vodkathumbscrewingly: 24076308 .cfa +",
144            cfi.Serialize());
145}
146
147TEST_F(Simple, RulesOverride) {
148  ExpectNoMemoryReferences();
149
150  cfi.SetCFARule("330903416631436410");
151  cfi.SetRARule("5870666104170902211");
152  cfi.SetCFARule("2828089117179001");
153  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
154                                            &caller_registers));
155  ASSERT_EQ(2U, caller_registers.size());
156  ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]);
157  ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
158  ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
159            cfi.Serialize());
160}
161
162class Scope: public CFIFixture, public Test { };
163
164// There should be no value for .cfa in scope when evaluating the CFA rule.
165TEST_F(Scope, CFALacksCFA) {
166  ExpectNoMemoryReferences();
167
168  cfi.SetCFARule(".cfa");
169  cfi.SetRARule("0");
170  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
171                                             &caller_registers));
172}
173
174// There should be no value for .ra in scope when evaluating the CFA rule.
175TEST_F(Scope, CFALacksRA) {
176  ExpectNoMemoryReferences();
177
178  cfi.SetCFARule(".ra");
179  cfi.SetRARule("0");
180  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
181                                             &caller_registers));
182}
183
184// The current frame's registers should be in scope when evaluating
185// the CFA rule.
186TEST_F(Scope, CFASeesCurrentRegs) {
187  ExpectNoMemoryReferences();
188
189  registers[".baraminology"] = 0x06a7bc63e4f13893ULL;
190  registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL;
191  cfi.SetCFARule(".baraminology .ornithorhynchus +");
192  cfi.SetRARule("0");
193  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
194                                            &caller_registers));
195  ASSERT_EQ(2U, caller_registers.size());
196  ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
197            caller_registers[".cfa"]);
198}
199
200// .cfa should be in scope in the return address expression.
201TEST_F(Scope, RASeesCFA) {
202  ExpectNoMemoryReferences();
203
204  cfi.SetCFARule("48364076");
205  cfi.SetRARule(".cfa");
206  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
207                                            &caller_registers));
208  ASSERT_EQ(2U, caller_registers.size());
209  ASSERT_EQ(48364076U, caller_registers[".ra"]);
210}
211
212// There should be no value for .ra in scope when evaluating the CFA rule.
213TEST_F(Scope, RALacksRA) {
214  ExpectNoMemoryReferences();
215
216  cfi.SetCFARule("0");
217  cfi.SetRARule(".ra");
218  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
219                                             &caller_registers));
220}
221
222// The current frame's registers should be in scope in the return
223// address expression.
224TEST_F(Scope, RASeesCurrentRegs) {
225  ExpectNoMemoryReferences();
226
227  registers["noachian"] = 0x54dc4a5d8e5eb503ULL;
228  cfi.SetCFARule("10359370");
229  cfi.SetRARule("noachian");
230  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
231                                            &caller_registers));
232  ASSERT_EQ(2U, caller_registers.size());
233  ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]);
234}
235
236// .cfa should be in scope for register rules.
237TEST_F(Scope, RegistersSeeCFA) {
238  ExpectNoMemoryReferences();
239
240  cfi.SetCFARule("6515179");
241  cfi.SetRARule(".cfa");
242  cfi.SetRegisterRule("rogerian", ".cfa");
243  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
244                                            &caller_registers));
245  ASSERT_EQ(3U, caller_registers.size());
246  ASSERT_EQ(6515179U, caller_registers["rogerian"]);
247}
248
249// The return address should not be in scope for register rules.
250TEST_F(Scope, RegsLackRA) {
251  ExpectNoMemoryReferences();
252
253  cfi.SetCFARule("42740329");
254  cfi.SetRARule("27045204");
255  cfi.SetRegisterRule("$r1", ".ra");
256  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
257                                             &caller_registers));
258}
259
260// Register rules can see the current frame's register values.
261TEST_F(Scope, RegsSeeRegs) {
262  ExpectNoMemoryReferences();
263
264  registers["$r1"] = 0x6ed3582c4bedb9adULL;
265  registers["$r2"] = 0xd27d9e742b8df6d0ULL;
266  cfi.SetCFARule("88239303");
267  cfi.SetRARule("30503835");
268  cfi.SetRegisterRule("$r1", "$r1 42175211 = $r2");
269  cfi.SetRegisterRule("$r2", "$r2 21357221 = $r1");
270  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
271                                            &caller_registers));
272  ASSERT_EQ(4U, caller_registers.size());
273  ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]);
274  ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]);
275}
276
277// Each rule's temporaries are separate.
278TEST_F(Scope, SeparateTempsRA) {
279  ExpectNoMemoryReferences();
280
281  cfi.SetCFARule("$temp1 76569129 = $temp1");
282  cfi.SetRARule("0");
283  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
284                                            &caller_registers));
285
286  cfi.SetCFARule("$temp1 76569129 = $temp1");
287  cfi.SetRARule("$temp1");
288  ASSERT_FALSE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
289                                             &caller_registers));
290}
291
292class MockCFIRuleParserHandler: public CFIRuleParser::Handler {
293 public:
294  MOCK_METHOD1(CFARule, void(const string &));
295  MOCK_METHOD1(RARule,  void(const string &));
296  MOCK_METHOD2(RegisterRule, void(const string &, const string &));
297};
298
299// A fixture class for testing CFIRuleParser.
300class CFIParserFixture {
301 public:
302  CFIParserFixture() : parser(&mock_handler) {
303    // Expect no parsing results to be reported to mock_handler. Individual
304    // tests can override this.
305    EXPECT_CALL(mock_handler, CFARule(_)).Times(0);
306    EXPECT_CALL(mock_handler, RARule(_)).Times(0);
307    EXPECT_CALL(mock_handler, RegisterRule(_, _)).Times(0);
308  }
309
310  MockCFIRuleParserHandler mock_handler;
311  CFIRuleParser parser;
312};
313
314class Parser: public CFIParserFixture, public Test { };
315
316TEST_F(Parser, Empty) {
317  EXPECT_FALSE(parser.Parse(""));
318}
319
320TEST_F(Parser, LoneColon) {
321  EXPECT_FALSE(parser.Parse(":"));
322}
323
324TEST_F(Parser, CFANoExpr) {
325  EXPECT_FALSE(parser.Parse(".cfa:"));
326}
327
328TEST_F(Parser, CFANoColonNoExpr) {
329  EXPECT_FALSE(parser.Parse(".cfa"));
330}
331
332TEST_F(Parser, RANoExpr) {
333  EXPECT_FALSE(parser.Parse(".ra:"));
334}
335
336TEST_F(Parser, RANoColonNoExpr) {
337  EXPECT_FALSE(parser.Parse(".ra"));
338}
339
340TEST_F(Parser, RegNoExpr) {
341  EXPECT_FALSE(parser.Parse("reg:"));
342}
343
344TEST_F(Parser, NoName) {
345  EXPECT_FALSE(parser.Parse("expr"));
346}
347
348TEST_F(Parser, NoNameTwo) {
349  EXPECT_FALSE(parser.Parse("expr1 expr2"));
350}
351
352TEST_F(Parser, StartsWithExpr) {
353  EXPECT_FALSE(parser.Parse("expr1 reg: expr2"));
354}
355
356TEST_F(Parser, CFA) {
357  EXPECT_CALL(mock_handler, CFARule("spleen")).WillOnce(Return());
358  EXPECT_TRUE(parser.Parse(".cfa: spleen"));
359}
360
361TEST_F(Parser, RA) {
362  EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return());
363  EXPECT_TRUE(parser.Parse(".ra: notoriety"));
364}
365
366TEST_F(Parser, Reg) {
367  EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous"))
368      .WillOnce(Return());
369  EXPECT_TRUE(parser.Parse("nemo: mellifluous"));
370}
371
372TEST_F(Parser, CFARARegs) {
373  EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return());
374  EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return());
375  EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian"))
376      .WillOnce(Return());
377  EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius"))
378      .WillOnce(Return());
379  EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression "
380                    "galba: praetorian otho: vitellius"));
381}
382
383TEST_F(Parser, Whitespace) {
384  EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression"))
385      .WillOnce(Return());
386  EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression"))
387      .WillOnce(Return());
388  EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n "
389                           "expression  \n"));
390}
391
392TEST_F(Parser, WhitespaceLoneColon) {
393  EXPECT_FALSE(parser.Parse("  \n:\t  "));
394}
395
396TEST_F(Parser, EmptyName) {
397  EXPECT_CALL(mock_handler, RegisterRule("reg", _))
398      .Times(AtMost(1))
399      .WillRepeatedly(Return());
400  EXPECT_FALSE(parser.Parse("reg: expr1 : expr2"));
401}
402
403TEST_F(Parser, RuleLoneColon) {
404  EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
405      .Times(AtMost(1))
406      .WillRepeatedly(Return());
407  EXPECT_FALSE(parser.Parse(" r1:   expr   :"));
408}
409
410TEST_F(Parser, RegNoExprRule) {
411  EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
412      .Times(AtMost(1))
413      .WillRepeatedly(Return());
414  EXPECT_FALSE(parser.Parse("r0: r1:   expr"));
415}
416
417class ParseHandlerFixture: public CFIFixture {
418 public:
419  ParseHandlerFixture() : CFIFixture(), handler(&cfi) { }
420  CFIFrameInfoParseHandler handler;
421};
422
423class ParseHandler: public ParseHandlerFixture, public Test { };
424
425TEST_F(ParseHandler, CFARARule) {
426  handler.CFARule("reg-for-cfa");
427  handler.RARule("reg-for-ra");
428  registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
429  registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
430  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
431                                            &caller_registers));
432  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
433  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
434}
435
436TEST_F(ParseHandler, RegisterRules) {
437  handler.CFARule("reg-for-cfa");
438  handler.RARule("reg-for-ra");
439  handler.RegisterRule("reg1", "reg-for-reg1");
440  handler.RegisterRule("reg2", "reg-for-reg2");
441  registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
442  registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
443  registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL;
444  registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL;
445  ASSERT_TRUE(cfi.FindCallerRegs<u_int64_t>(registers, memory,
446                                            &caller_registers));
447  ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
448  ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
449  ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]);
450  ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]);
451}
452
453struct SimpleCFIWalkerFixture {
454  struct RawContext {
455    u_int64_t r0, r1, r2, r3, r4, sp, pc;
456  };
457  enum Validity {
458    R0_VALID = 0x01,
459    R1_VALID = 0x02,
460    R2_VALID = 0x04,
461    R3_VALID = 0x08,
462    R4_VALID = 0x10,
463    SP_VALID = 0x20,
464    PC_VALID = 0x40
465  };
466  typedef SimpleCFIWalker<u_int64_t, RawContext> CFIWalker;
467
468  SimpleCFIWalkerFixture()
469      : walker(register_map,
470               sizeof(register_map) / sizeof(register_map[0])) { }
471
472  static CFIWalker::RegisterSet register_map[7];
473  CFIFrameInfo call_frame_info;
474  CFIWalker walker;
475  MockMemoryRegion memory;
476  RawContext callee_context, caller_context;
477};
478
479SimpleCFIWalkerFixture::CFIWalker::RegisterSet
480SimpleCFIWalkerFixture::register_map[7] = {
481  { "r0", NULL,   true,  R0_VALID, &RawContext::r0 },
482  { "r1", NULL,   true,  R1_VALID, &RawContext::r1 },
483  { "r2", NULL,   false, R2_VALID, &RawContext::r2 },
484  { "r3", NULL,   false, R3_VALID, &RawContext::r3 },
485  { "r4", NULL,   true,  R4_VALID, &RawContext::r4 },
486  { "sp", ".cfa", true,  SP_VALID, &RawContext::sp },
487  { "pc", ".ra",  true,  PC_VALID, &RawContext::pc },
488};
489
490class SimpleWalker: public SimpleCFIWalkerFixture, public Test { };
491
492TEST_F(SimpleWalker, Walk) {
493  // Stack_top is the current stack pointer, pointing to the lowest
494  // address of a frame that looks like this (all 64-bit words):
495  //
496  // sp ->  saved r0
497  //        garbage
498  //        return address
499  // cfa -> 
500  //
501  // r0 has been saved on the stack.
502  // r1 has been saved in r2.
503  // r2 and r3 are not recoverable.
504  // r4 is not recoverable, even though it is a callee-saves register.
505  //    Some earlier frame's unwinder must have failed to recover it.
506
507  u_int64_t stack_top = 0x83254944b20d5512ULL;
508
509  // Saved r0.
510  EXPECT_CALL(memory,
511              GetMemoryAtAddress(stack_top, A<u_int64_t *>()))
512      .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xdc1975eba8602302ULL),
513                            Return(true)));
514  // Saved return address.
515  EXPECT_CALL(memory,
516              GetMemoryAtAddress(stack_top + 16, A<u_int64_t *>()))
517      .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL),
518                            Return(true)));
519
520  call_frame_info.SetCFARule("sp 24 +");
521  call_frame_info.SetRARule(".cfa 8 - ^");
522  call_frame_info.SetRegisterRule("r0", ".cfa 24 - ^");
523  call_frame_info.SetRegisterRule("r1", "r2");
524
525  callee_context.r0 = 0x94e030ca79edd119ULL;
526  callee_context.r1 = 0x937b4d7e95ce52d9ULL;
527  callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1
528  // callee_context.r3 is not valid in callee.
529  // callee_context.r4 is not valid in callee.
530  callee_context.sp = stack_top;
531  callee_context.pc = 0x25b21b224311d280ULL;
532  int callee_validity = R0_VALID | R1_VALID | R2_VALID | SP_VALID | PC_VALID;
533
534  memset(&caller_context, 0, sizeof(caller_context));
535
536  int caller_validity;
537  EXPECT_TRUE(walker.FindCallerRegisters(memory, call_frame_info,
538                                         callee_context, callee_validity,
539                                         &caller_context, &caller_validity));
540  EXPECT_EQ(R0_VALID | R1_VALID | SP_VALID | PC_VALID, caller_validity);
541  EXPECT_EQ(0xdc1975eba8602302ULL, caller_context.r0);
542  EXPECT_EQ(0x5fe0027416b8b62aULL, caller_context.r1);
543  EXPECT_EQ(stack_top + 24,        caller_context.sp);
544  EXPECT_EQ(0xba5ad6d9acce28deULL, caller_context.pc);
545}