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