xref: /aosp_15_r20/external/google-breakpad/src/processor/stackwalker_arm64_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // Original author: Jim Blandy <[email protected]> <[email protected]>
30 
31 // stackwalker_arm64_unittest.cc: Unit tests for StackwalkerARM64 class.
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>  // Must come first
35 #endif
36 
37 #include <string.h>
38 #include <string>
39 #include <vector>
40 
41 #include "breakpad_googletest_includes.h"
42 #include "common/test_assembler.h"
43 #include "common/using_std_string.h"
44 #include "google_breakpad/common/minidump_format.h"
45 #include "google_breakpad/processor/basic_source_line_resolver.h"
46 #include "google_breakpad/processor/call_stack.h"
47 #include "google_breakpad/processor/code_module.h"
48 #include "google_breakpad/processor/source_line_resolver_interface.h"
49 #include "google_breakpad/processor/stack_frame_cpu.h"
50 #include "processor/stackwalker_unittest_utils.h"
51 #include "processor/stackwalker_arm64.h"
52 #include "processor/windows_frame_info.h"
53 
54 using google_breakpad::BasicSourceLineResolver;
55 using google_breakpad::CallStack;
56 using google_breakpad::CodeModule;
57 using google_breakpad::StackFrameSymbolizer;
58 using google_breakpad::StackFrame;
59 using google_breakpad::StackFrameARM64;
60 using google_breakpad::Stackwalker;
61 using google_breakpad::StackwalkerARM64;
62 using google_breakpad::SystemInfo;
63 using google_breakpad::WindowsFrameInfo;
64 using google_breakpad::test_assembler::kLittleEndian;
65 using google_breakpad::test_assembler::Label;
66 using google_breakpad::test_assembler::Section;
67 using std::vector;
68 using testing::_;
69 using testing::AnyNumber;
70 using testing::DoAll;
71 using testing::Return;
72 using testing::SetArgumentPointee;
73 using testing::Test;
74 
75 class StackwalkerARM64Fixture {
76  public:
StackwalkerARM64Fixture()77   StackwalkerARM64Fixture()
78     : stack_section(kLittleEndian),
79       // Give the two modules reasonable standard locations and names
80       // for tests to play with.
81       module1(0x40000000, 0x10000, "module1", "version1"),
82       module2(0x50000000, 0x10000, "module2", "version2") {
83     // Identify the system as an iOS system.
84     system_info.os = "iOS";
85     system_info.os_short = "ios";
86     system_info.cpu = "arm64";
87     system_info.cpu_info = "";
88 
89     // Put distinctive values in the raw CPU context.
90     BrandContext(&raw_context);
91 
92     // Create some modules with some stock debugging information.
93     modules.Add(&module1);
94     modules.Add(&module2);
95 
96     // By default, none of the modules have symbol info; call
97     // SetModuleSymbols to override this.
98     EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
99       .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
100 
101     // Avoid GMOCK WARNING "Uninteresting mock function call - returning
102     // directly" for FreeSymbolData().
103     EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
104 
105     // Reset max_frames_scanned since it's static.
106     Stackwalker::set_max_frames_scanned(1024);
107   }
108 
109   // Set the Breakpad symbol information that supplier should return for
110   // MODULE to INFO.
SetModuleSymbols(MockCodeModule * module,const string & info)111   void SetModuleSymbols(MockCodeModule* module, const string& info) {
112     size_t buffer_size;
113     char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
114     EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
115       .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
116                             SetArgumentPointee<4>(buffer_size),
117                             Return(MockSymbolSupplier::FOUND)));
118   }
119 
120   // Populate stack_region with the contents of stack_section. Use
121   // stack_section.start() as the region's starting address.
RegionFromSection()122   void RegionFromSection() {
123     string contents;
124     ASSERT_TRUE(stack_section.GetContents(&contents));
125     stack_region.Init(stack_section.start().Value(), contents);
126   }
127 
128   // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
BrandContext(MDRawContextARM64 * raw_context)129   void BrandContext(MDRawContextARM64 *raw_context) {
130     uint8_t x = 173;
131     for (size_t i = 0; i < sizeof(*raw_context); i++)
132       reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17);
133   }
134 
135   SystemInfo system_info;
136   MDRawContextARM64 raw_context;
137   Section stack_section;
138   MockMemoryRegion stack_region;
139   MockCodeModule module1;
140   MockCodeModule module2;
141   MockCodeModules modules;
142   MockSymbolSupplier supplier;
143   BasicSourceLineResolver resolver;
144   CallStack call_stack;
145   const vector<StackFrame*>* frames;
146 };
147 
148 class SanityCheck: public StackwalkerARM64Fixture, public Test { };
149 
TEST_F(SanityCheck,NoResolver)150 TEST_F(SanityCheck, NoResolver) {
151   // Since the context's frame pointer is garbage, the stack walk will end after
152   // the first frame.
153   StackFrameSymbolizer frame_symbolizer(NULL, NULL);
154   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
155                           &frame_symbolizer);
156   // This should succeed even without a resolver or supplier.
157   vector<const CodeModule*> modules_without_symbols;
158   vector<const CodeModule*> modules_with_corrupt_symbols;
159   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
160                           &modules_with_corrupt_symbols));
161   ASSERT_EQ(0U, modules_without_symbols.size());
162   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
163   frames = call_stack.frames();
164   ASSERT_EQ(1U, frames->size());
165   StackFrameARM64 *frame = static_cast<StackFrameARM64*>(frames->at(0));
166   // Check that the values from the original raw context made it
167   // through to the context in the stack frame.
168   EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
169 }
170 
171 class GetContextFrame: public StackwalkerARM64Fixture, public Test { };
172 
173 // The stackwalker should be able to produce the context frame even
174 // without stack memory present.
TEST_F(GetContextFrame,NoStackMemory)175 TEST_F(GetContextFrame, NoStackMemory) {
176   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
177   StackwalkerARM64 walker(&system_info, &raw_context, NULL, &modules,
178                           &frame_symbolizer);
179   vector<const CodeModule*> modules_without_symbols;
180   vector<const CodeModule*> modules_with_corrupt_symbols;
181   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
182                           &modules_with_corrupt_symbols));
183   ASSERT_EQ(0U, modules_without_symbols.size());
184   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
185   frames = call_stack.frames();
186   ASSERT_EQ(1U, frames->size());
187   StackFrameARM64 *frame = static_cast<StackFrameARM64*>(frames->at(0));
188   // Check that the values from the original raw context made it
189   // through to the context in the stack frame.
190   EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
191 }
192 
193 class GetCallerFrame: public StackwalkerARM64Fixture, public Test { };
194 
TEST_F(GetCallerFrame,ScanWithoutSymbols)195 TEST_F(GetCallerFrame, ScanWithoutSymbols) {
196   // When the stack walker resorts to scanning the stack,
197   // only addresses located within loaded modules are
198   // considered valid return addresses.
199   // Force scanning through three frames to ensure that the
200   // stack pointer is set properly in scan-recovered frames.
201   stack_section.start() = 0x80000000;
202   uint64_t return_address1 = 0x50000100;
203   uint64_t return_address2 = 0x50000900;
204   Label frame1_sp, frame2_sp;
205   stack_section
206     // frame 0
207     .Append(16, 0)                      // space
208 
209     .D64(0x40090000)                    // junk that's not
210     .D64(0x60000000)                    // a return address
211 
212     .D64(return_address1)               // actual return address
213     // frame 1
214     .Mark(&frame1_sp)
215     .Append(16, 0)                      // space
216 
217     .D64(0xF0000000)                    // more junk
218     .D64(0x0000000D)
219 
220     .D64(return_address2)               // actual return address
221     // frame 2
222     .Mark(&frame2_sp)
223     .Append(64, 0);                     // end of stack
224   RegionFromSection();
225 
226   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
227   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
228 
229   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
230   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
231                           &frame_symbolizer);
232   vector<const CodeModule*> modules_without_symbols;
233   vector<const CodeModule*> modules_with_corrupt_symbols;
234   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
235                           &modules_with_corrupt_symbols));
236   ASSERT_EQ(2U, modules_without_symbols.size());
237   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
238   ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
239   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
240   frames = call_stack.frames();
241   ASSERT_EQ(3U, frames->size());
242 
243   StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
244   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
245   ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
246             frame0->context_validity);
247   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
248 
249   StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
250   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
251   ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
252              StackFrameARM64::CONTEXT_VALID_SP),
253             frame1->context_validity);
254   EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
255   EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
256 
257   StackFrameARM64 *frame2 = static_cast<StackFrameARM64*>(frames->at(2));
258   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
259   ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
260              StackFrameARM64::CONTEXT_VALID_SP),
261             frame2->context_validity);
262   EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
263   EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
264 }
265 
TEST_F(GetCallerFrame,ScanWithFunctionSymbols)266 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
267   // During stack scanning, if a potential return address
268   // is located within a loaded module that has symbols,
269   // it is only considered a valid return address if it
270   // lies within a function's bounds.
271   stack_section.start() = 0x80000000;
272   uint64_t return_address = 0x50000200;
273   Label frame1_sp;
274 
275   stack_section
276     // frame 0
277     .Append(16, 0)                      // space
278 
279     .D64(0x40090000)                    // junk that's not
280     .D64(0x60000000)                    // a return address
281 
282     .D64(0x40001000)                    // a couple of plausible addresses
283     .D64(0x5000F000)                    // that are not within functions
284 
285     .D64(return_address)                // actual return address
286     // frame 1
287     .Mark(&frame1_sp)
288     .Append(64, 0);                     // end of stack
289   RegionFromSection();
290 
291   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40000200;
292   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
293 
294   SetModuleSymbols(&module1,
295                    // The youngest frame's function.
296                    "FUNC 100 400 10 monotreme\n");
297   SetModuleSymbols(&module2,
298                    // The calling frame's function.
299                    "FUNC 100 400 10 marsupial\n");
300 
301   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
302   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
303                           &frame_symbolizer);
304   vector<const CodeModule*> modules_without_symbols;
305   vector<const CodeModule*> modules_with_corrupt_symbols;
306   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
307                           &modules_with_corrupt_symbols));
308   ASSERT_EQ(0U, modules_without_symbols.size());
309   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
310   frames = call_stack.frames();
311   ASSERT_EQ(2U, frames->size());
312 
313   StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
314   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
315   ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
316             frame0->context_validity);
317   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
318   EXPECT_EQ("monotreme", frame0->function_name);
319   EXPECT_EQ(0x40000100ULL, frame0->function_base);
320 
321   StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
322   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
323   ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
324              StackFrameARM64::CONTEXT_VALID_SP),
325             frame1->context_validity);
326   EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
327   EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
328   EXPECT_EQ("marsupial", frame1->function_name);
329   EXPECT_EQ(0x50000100ULL, frame1->function_base);
330 }
331 
TEST_F(GetCallerFrame,ScanFirstFrame)332 TEST_F(GetCallerFrame, ScanFirstFrame) {
333   // If the stackwalker resorts to stack scanning, it will scan much
334   // farther to find the caller of the context frame.
335   stack_section.start() = 0x80000000;
336   uint64_t return_address1 = 0x50000100;
337   uint64_t return_address2 = 0x50000900;
338   Label frame1_sp, frame2_sp;
339   stack_section
340     // frame 0
341     .Append(32, 0)                      // space
342 
343     .D64(0x40090000)                    // junk that's not
344     .D64(0x60000000)                    // a return address
345 
346     .Append(96, 0)                      // more space
347 
348     .D64(return_address1)               // actual return address
349     // frame 1
350     .Mark(&frame1_sp)
351     .Append(32, 0)                      // space
352 
353     .D64(0xF0000000)                    // more junk
354     .D64(0x0000000D)
355 
356     .Append(336, 0)                     // more space
357 
358     .D64(return_address2)               // actual return address
359                                         // (won't be found)
360     // frame 2
361     .Mark(&frame2_sp)
362     .Append(64, 0);                     // end of stack
363   RegionFromSection();
364 
365   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
366   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
367 
368   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
369   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
370                           &frame_symbolizer);
371   vector<const CodeModule*> modules_without_symbols;
372   vector<const CodeModule*> modules_with_corrupt_symbols;
373   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
374                           &modules_with_corrupt_symbols));
375   ASSERT_EQ(2U, modules_without_symbols.size());
376   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
377   ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
378   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
379   frames = call_stack.frames();
380   ASSERT_EQ(2U, frames->size());
381 
382   StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
383   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
384   ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
385             frame0->context_validity);
386   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
387 
388   StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
389   EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
390   ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
391              StackFrameARM64::CONTEXT_VALID_SP),
392             frame1->context_validity);
393   EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
394   EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
395 }
396 
397 // Test that set_max_frames_scanned prevents using stack scanning
398 // to find caller frames.
TEST_F(GetCallerFrame,ScanningNotAllowed)399 TEST_F(GetCallerFrame, ScanningNotAllowed) {
400   // When the stack walker resorts to scanning the stack,
401   // only addresses located within loaded modules are
402   // considered valid return addresses.
403   stack_section.start() = 0x80000000;
404   uint64_t return_address1 = 0x50000100;
405   uint64_t return_address2 = 0x50000900;
406   Label frame1_sp, frame2_sp;
407   stack_section
408     // frame 0
409     .Append(16, 0)                      // space
410 
411     .D64(0x40090000)                    // junk that's not
412     .D64(0x60000000)                    // a return address
413 
414     .D64(return_address1)               // actual return address
415     // frame 1
416     .Mark(&frame1_sp)
417     .Append(16, 0)                      // space
418 
419     .D64(0xF0000000)                    // more junk
420     .D64(0x0000000D)
421 
422     .D64(return_address2)               // actual return address
423     // frame 2
424     .Mark(&frame2_sp)
425     .Append(64, 0);                     // end of stack
426   RegionFromSection();
427 
428   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
429   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
430 
431   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
432   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
433                           &frame_symbolizer);
434   Stackwalker::set_max_frames_scanned(0);
435 
436   vector<const CodeModule*> modules_without_symbols;
437   vector<const CodeModule*> modules_with_corrupt_symbols;
438   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
439                           &modules_with_corrupt_symbols));
440   ASSERT_EQ(1U, modules_without_symbols.size());
441   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
442   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
443   frames = call_stack.frames();
444   ASSERT_EQ(1U, frames->size());
445 
446   StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
447   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
448   ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
449             frame0->context_validity);
450   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
451 }
452 
453 class GetFramesByFramePointer: public StackwalkerARM64Fixture, public Test { };
454 
TEST_F(GetFramesByFramePointer,OnlyFramePointer)455 TEST_F(GetFramesByFramePointer, OnlyFramePointer) {
456   stack_section.start() = 0x80000000;
457   uint64_t return_address1 = 0x50000100;
458   uint64_t return_address2 = 0x50000900;
459   Label frame1_sp, frame2_sp;
460   Label frame1_fp, frame2_fp;
461   stack_section
462     // frame 0
463     .Append(64, 0)           // Whatever values on the stack.
464     .D64(0x0000000D)         // junk that's not
465     .D64(0xF0000000)         // a return address.
466 
467     .Mark(&frame1_fp)        // Next fp will point to the next value.
468     .D64(frame2_fp)          // Save current frame pointer.
469     .D64(return_address2)    // Save current link register.
470     .Mark(&frame1_sp)
471 
472     // frame 1
473     .Append(64, 0)           // Whatever values on the stack.
474     .D64(0x0000000D)         // junk that's not
475     .D64(0xF0000000)         // a return address.
476 
477     .Mark(&frame2_fp)
478     .D64(0)
479     .D64(0)
480     .Mark(&frame2_sp)
481 
482     // frame 2
483     .Append(64, 0)           // Whatever values on the stack.
484     .D64(0x0000000D)         // junk that's not
485     .D64(0xF0000000);        // a return address.
486   RegionFromSection();
487 
488 
489   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
490   raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = return_address1;
491   raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = frame1_fp.Value();
492   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
493 
494   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
495   StackwalkerARM64 walker(&system_info, &raw_context,
496                           &stack_region, &modules, &frame_symbolizer);
497 
498   vector<const CodeModule*> modules_without_symbols;
499   vector<const CodeModule*> modules_with_corrupt_symbols;
500   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
501                           &modules_with_corrupt_symbols));
502   ASSERT_EQ(2U, modules_without_symbols.size());
503   ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
504   ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
505   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
506   frames = call_stack.frames();
507   ASSERT_EQ(3U, frames->size());
508 
509   StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
510   EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
511   ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
512             frame0->context_validity);
513   EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
514 
515   StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
516   EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
517   ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
518              StackFrameARM64::CONTEXT_VALID_LR |
519              StackFrameARM64::CONTEXT_VALID_FP |
520              StackFrameARM64::CONTEXT_VALID_SP),
521             frame1->context_validity);
522   EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
523   EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
524   EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
525   EXPECT_EQ(frame2_fp.Value(),
526             frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
527 
528   StackFrameARM64 *frame2 = static_cast<StackFrameARM64*>(frames->at(2));
529   EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust);
530   ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
531              StackFrameARM64::CONTEXT_VALID_LR |
532              StackFrameARM64::CONTEXT_VALID_FP |
533              StackFrameARM64::CONTEXT_VALID_SP),
534             frame2->context_validity);
535   EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
536   EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
537   EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
538   EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
539 }
540 
541 struct CFIFixture: public StackwalkerARM64Fixture {
CFIFixtureCFIFixture542   CFIFixture() {
543     // Provide a bunch of STACK CFI records; we'll walk to the caller
544     // from every point in this series, expecting to find the same set
545     // of register values.
546     SetModuleSymbols(&module1,
547                      // The youngest frame's function.
548                      "FUNC 4000 1000 10 enchiridion\n"
549                      // Initially, nothing has been pushed on the stack,
550                      // and the return address is still in the link
551                      // register (x30).
552                      "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: x30\n"
553                      // Push x19, x20, the frame pointer and the link register.
554                      "STACK CFI 4001 .cfa: sp 32 + .ra: .cfa -8 + ^"
555                      " x19: .cfa -32 + ^ x20: .cfa -24 + ^ "
556                      " x29: .cfa -16 + ^\n"
557                      // Save x19..x22 in x0..x3: verify that we populate
558                      // the youngest frame with all the values we have.
559                      "STACK CFI 4002 x19: x0 x20: x1 x21: x2 x22: x3\n"
560                      // Restore x19..x22. Save the non-callee-saves register x1.
561                      "STACK CFI 4003 .cfa: sp 40 + x1: .cfa 40 - ^"
562                      " x19: x19 x20: x20 x21: x21 x22: x22\n"
563                      // Move the .cfa back eight bytes, to point at the return
564                      // address, and restore the sp explicitly.
565                      "STACK CFI 4005 .cfa: sp 32 + x1: .cfa 32 - ^"
566                      " x29: .cfa 8 - ^ .ra: .cfa ^ sp: .cfa 8 +\n"
567                      // Recover the PC explicitly from a new stack slot;
568                      // provide garbage for the .ra.
569                      "STACK CFI 4006 .cfa: sp 40 + pc: .cfa 40 - ^\n"
570 
571                      // The calling function.
572                      "FUNC 5000 1000 10 epictetus\n"
573                      // Mark it as end of stack.
574                      "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n"
575 
576                      // A function whose CFI makes the stack pointer
577                      // go backwards.
578                      "FUNC 6000 1000 20 palinal\n"
579                      "STACK CFI INIT 6000 1000 .cfa: sp 8 - .ra: x30\n"
580 
581                      // A function with CFI expressions that can't be
582                      // evaluated.
583                      "FUNC 7000 1000 20 rhetorical\n"
584                      "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n");
585 
586     // Provide some distinctive values for the caller's registers.
587     expected.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040005510L;
588     expected.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
589     expected.iregs[19] = 0x5e68b5d5b5d55e68L;
590     expected.iregs[20] = 0x34f3ebd1ebd134f3L;
591     expected.iregs[21] = 0x74bca31ea31e74bcL;
592     expected.iregs[22] = 0x16b32dcb2dcb16b3L;
593     expected.iregs[23] = 0x21372ada2ada2137L;
594     expected.iregs[24] = 0x557dbbbbbbbb557dL;
595     expected.iregs[25] = 0x8ca748bf48bf8ca7L;
596     expected.iregs[26] = 0x21f0ab46ab4621f0L;
597     expected.iregs[27] = 0x146732b732b71467L;
598     expected.iregs[28] = 0xa673645fa673645fL;
599     expected.iregs[MD_CONTEXT_ARM64_REG_FP] = 0xe11081128112e110L;
600 
601     // Expect CFI to recover all callee-saves registers. Since CFI is the
602     // only stack frame construction technique we have, aside from the
603     // context frame itself, there's no way for us to have a set of valid
604     // registers smaller than this.
605     expected_validity = (StackFrameARM64::CONTEXT_VALID_PC  |
606                          StackFrameARM64::CONTEXT_VALID_SP  |
607                          StackFrameARM64::CONTEXT_VALID_X19 |
608                          StackFrameARM64::CONTEXT_VALID_X20 |
609                          StackFrameARM64::CONTEXT_VALID_X21 |
610                          StackFrameARM64::CONTEXT_VALID_X22 |
611                          StackFrameARM64::CONTEXT_VALID_X23 |
612                          StackFrameARM64::CONTEXT_VALID_X24 |
613                          StackFrameARM64::CONTEXT_VALID_X25 |
614                          StackFrameARM64::CONTEXT_VALID_X26 |
615                          StackFrameARM64::CONTEXT_VALID_X27 |
616                          StackFrameARM64::CONTEXT_VALID_X28 |
617                          StackFrameARM64::CONTEXT_VALID_FP);
618 
619     // By default, context frames provide all registers, as normal.
620     context_frame_validity = StackFrameARM64::CONTEXT_VALID_ALL;
621 
622     // By default, registers are unchanged.
623     raw_context = expected;
624   }
625 
626   // Walk the stack, using stack_section as the contents of the stack
627   // and raw_context as the current register values. (Set the stack
628   // pointer to the stack's starting address.) Expect two stack
629   // frames; in the older frame, expect the callee-saves registers to
630   // have values matching those in 'expected'.
CheckWalkCFIFixture631   void CheckWalk() {
632     RegionFromSection();
633     raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
634 
635     StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
636     StackwalkerARM64 walker(&system_info, &raw_context, &stack_region,
637                             &modules, &frame_symbolizer);
638     walker.SetContextFrameValidity(context_frame_validity);
639     vector<const CodeModule*> modules_without_symbols;
640     vector<const CodeModule*> modules_with_corrupt_symbols;
641     ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
642                             &modules_with_corrupt_symbols));
643     ASSERT_EQ(0U, modules_without_symbols.size());
644     ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
645     frames = call_stack.frames();
646     ASSERT_EQ(2U, frames->size());
647 
648     StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
649     EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
650     ASSERT_EQ(context_frame_validity, frame0->context_validity);
651     EXPECT_EQ("enchiridion", frame0->function_name);
652     EXPECT_EQ(0x0000000040004000UL, frame0->function_base);
653 
654     StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
655     EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
656     ASSERT_EQ(expected_validity, frame1->context_validity);
657     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X1)
658       EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]);
659     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X19)
660       EXPECT_EQ(expected.iregs[19], frame1->context.iregs[19]);
661     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X20)
662       EXPECT_EQ(expected.iregs[20], frame1->context.iregs[20]);
663     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X21)
664       EXPECT_EQ(expected.iregs[21], frame1->context.iregs[21]);
665     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X22)
666       EXPECT_EQ(expected.iregs[22], frame1->context.iregs[22]);
667     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X23)
668       EXPECT_EQ(expected.iregs[23], frame1->context.iregs[23]);
669     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X24)
670       EXPECT_EQ(expected.iregs[24], frame1->context.iregs[24]);
671     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X25)
672       EXPECT_EQ(expected.iregs[25], frame1->context.iregs[25]);
673     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X26)
674       EXPECT_EQ(expected.iregs[26], frame1->context.iregs[26]);
675     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X27)
676       EXPECT_EQ(expected.iregs[27], frame1->context.iregs[27]);
677     if (expected_validity & StackFrameARM64::CONTEXT_VALID_X28)
678       EXPECT_EQ(expected.iregs[28], frame1->context.iregs[28]);
679     if (expected_validity & StackFrameARM64::CONTEXT_VALID_FP)
680       EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_FP],
681                 frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
682 
683     // We would never have gotten a frame in the first place if the SP
684     // and PC weren't valid or ->instruction weren't set.
685     EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_SP],
686               frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
687     EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC],
688               frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
689     EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC],
690               frame1->instruction + 4);
691     EXPECT_EQ("epictetus", frame1->function_name);
692   }
693 
694   // The values we expect to find for the caller's registers.
695   MDRawContextARM64 expected;
696 
697   // The validity mask for expected.
698   uint64_t expected_validity;
699 
700   // The validity mask to impose on the context frame.
701   uint64_t context_frame_validity;
702 };
703 
704 class CFI: public CFIFixture, public Test { };
705 
TEST_F(CFI,At4000)706 TEST_F(CFI, At4000) {
707   stack_section.start() = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
708   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004000L;
709   raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L;
710   CheckWalk();
711 }
712 
TEST_F(CFI,At4001)713 TEST_F(CFI, At4001) {
714   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
715   stack_section
716     .D64(0x5e68b5d5b5d55e68L)   // saved x19
717     .D64(0x34f3ebd1ebd134f3L)   // saved x20
718     .D64(0xe11081128112e110L)   // saved fp
719     .D64(0x0000000040005510L)   // return address
720     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
721   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L;
722   // distinct callee x19, x20 and fp
723   raw_context.iregs[19] = 0xadc9f635a635adc9L;
724   raw_context.iregs[20] = 0x623135ac35ac6231L;
725   raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
726   CheckWalk();
727 }
728 
729 // As above, but unwind from a context that has only the PC and SP.
TEST_F(CFI,At4001LimitedValidity)730 TEST_F(CFI, At4001LimitedValidity) {
731   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
732   stack_section
733     .D64(0x5e68b5d5b5d55e68L)   // saved x19
734     .D64(0x34f3ebd1ebd134f3L)   // saved x20
735     .D64(0xe11081128112e110L)   // saved fp
736     .D64(0x0000000040005510L)   // return address
737     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
738   context_frame_validity =
739     StackFrameARM64::CONTEXT_VALID_PC | StackFrameARM64::CONTEXT_VALID_SP;
740   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L;
741   raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
742 
743   expected_validity = (StackFrameARM64::CONTEXT_VALID_PC
744                        | StackFrameARM64::CONTEXT_VALID_SP
745                        | StackFrameARM64::CONTEXT_VALID_FP
746                        | StackFrameARM64::CONTEXT_VALID_X19
747                        | StackFrameARM64::CONTEXT_VALID_X20);
748   CheckWalk();
749 }
750 
TEST_F(CFI,At4002)751 TEST_F(CFI, At4002) {
752   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
753   stack_section
754     .D64(0xff3dfb81fb81ff3dL)   // no longer saved x19
755     .D64(0x34f3ebd1ebd134f3L)   // no longer saved x20
756     .D64(0xe11081128112e110L)   // saved fp
757     .D64(0x0000000040005510L)   // return address
758     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
759   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004002L;
760   raw_context.iregs[0]  = 0x5e68b5d5b5d55e68L;  // saved x19
761   raw_context.iregs[1]  = 0x34f3ebd1ebd134f3L;  // saved x20
762   raw_context.iregs[2]  = 0x74bca31ea31e74bcL;  // saved x21
763   raw_context.iregs[3]  = 0x16b32dcb2dcb16b3L;  // saved x22
764   raw_context.iregs[19] = 0xadc9f635a635adc9L;  // distinct callee x19
765   raw_context.iregs[20] = 0x623135ac35ac6231L;  // distinct callee x20
766   raw_context.iregs[21] = 0xac4543564356ac45L;  // distinct callee x21
767   raw_context.iregs[22] = 0x2561562f562f2561L;  // distinct callee x22
768   // distinct callee fp
769   raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
770   CheckWalk();
771 }
772 
TEST_F(CFI,At4003)773 TEST_F(CFI, At4003) {
774   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
775   stack_section
776     .D64(0xdd5a48c848c8dd5aL)   // saved x1 (even though it's not callee-saves)
777     .D64(0xff3dfb81fb81ff3dL)   // no longer saved x19
778     .D64(0x34f3ebd1ebd134f3L)   // no longer saved x20
779     .D64(0xe11081128112e110L)   // saved fp
780     .D64(0x0000000040005510L)   // return address
781     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
782   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004003L;
783   // distinct callee x1 and fp
784   raw_context.iregs[1] = 0xfb756319fb756319L;
785   raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
786   // caller's x1
787   expected.iregs[1] = 0xdd5a48c848c8dd5aL;
788   expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
789   CheckWalk();
790 }
791 
792 // We have no new rule at module offset 0x4004, so the results here should
793 // be the same as those at module offset 0x4003.
TEST_F(CFI,At4004)794 TEST_F(CFI, At4004) {
795   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
796   stack_section
797     .D64(0xdd5a48c848c8dd5aL)   // saved x1 (even though it's not callee-saves)
798     .D64(0xff3dfb81fb81ff3dL)   // no longer saved x19
799     .D64(0x34f3ebd1ebd134f3L)   // no longer saved x20
800     .D64(0xe11081128112e110L)   // saved fp
801     .D64(0x0000000040005510L)   // return address
802     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
803   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004004L;
804   // distinct callee x1 and fp
805   raw_context.iregs[1] = 0xfb756319fb756319L;
806   raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
807   // caller's x1
808   expected.iregs[1] = 0xdd5a48c848c8dd5aL;
809   expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
810   CheckWalk();
811 }
812 
813 // Here we move the .cfa, but provide an explicit rule to recover the SP,
814 // so again there should be no change in the registers recovered.
TEST_F(CFI,At4005)815 TEST_F(CFI, At4005) {
816   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
817   stack_section
818     .D64(0xdd5a48c848c8dd5aL)   // saved x1 (even though it's not callee-saves)
819     .D64(0xff3dfb81fb81ff3dL)   // no longer saved x19
820     .D64(0x34f3ebd1ebd134f3L)   // no longer saved x20
821     .D64(0xe11081128112e110L)   // saved fp
822     .D64(0x0000000040005510L)   // return address
823     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
824   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004005L;
825   raw_context.iregs[1] = 0xfb756319fb756319L;  // distinct callee x1
826   expected.iregs[1] = 0xdd5a48c848c8dd5aL;     // caller's x1
827   expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
828   CheckWalk();
829 }
830 
831 // Here we provide an explicit rule for the PC, and have the saved .ra be
832 // bogus.
TEST_F(CFI,At4006)833 TEST_F(CFI, At4006) {
834   Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
835   stack_section
836     .D64(0x0000000040005510L)   // saved pc
837     .D64(0xdd5a48c848c8dd5aL)   // saved x1 (even though it's not callee-saves)
838     .D64(0xff3dfb81fb81ff3dL)   // no longer saved x19
839     .D64(0x34f3ebd1ebd134f3L)   // no longer saved x20
840     .D64(0xe11081128112e110L)   // saved fp
841     .D64(0xf8d157835783f8d1L)   // .ra rule recovers this, which is garbage
842     .Mark(&frame1_sp);          // This effectively sets stack_section.start().
843   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004006L;
844   raw_context.iregs[1] = 0xfb756319fb756319L;  // distinct callee x1
845   expected.iregs[1] = 0xdd5a48c848c8dd5aL;     // caller's x1
846   expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
847   CheckWalk();
848 }
849 
850 // Check that we reject rules that would cause the stack pointer to
851 // move in the wrong direction.
TEST_F(CFI,RejectBackwards)852 TEST_F(CFI, RejectBackwards) {
853   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040006000L;
854   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
855   raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L;
856   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
857   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
858                           &frame_symbolizer);
859   vector<const CodeModule*> modules_without_symbols;
860   vector<const CodeModule*> modules_with_corrupt_symbols;
861   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
862                           &modules_with_corrupt_symbols));
863   ASSERT_EQ(0U, modules_without_symbols.size());
864   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
865   frames = call_stack.frames();
866   ASSERT_EQ(1U, frames->size());
867 }
868 
869 // Check that we reject rules whose expressions' evaluation fails.
TEST_F(CFI,RejectBadExpressions)870 TEST_F(CFI, RejectBadExpressions) {
871   raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040007000L;
872   raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
873   StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
874   StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
875                           &frame_symbolizer);
876   vector<const CodeModule*> modules_without_symbols;
877   vector<const CodeModule*> modules_with_corrupt_symbols;
878   ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
879                           &modules_with_corrupt_symbols));
880   ASSERT_EQ(0U, modules_without_symbols.size());
881   ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
882   frames = call_stack.frames();
883   ASSERT_EQ(1U, frames->size());
884 }
885