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