1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,875 @@ 1.4 +// Copyright (c) 2010, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.34 + 1.35 +// stackwalker_arm_unittest.cc: Unit tests for StackwalkerARM class. 1.36 + 1.37 +#include <string.h> 1.38 +#include <string> 1.39 +#include <vector> 1.40 + 1.41 +#include "breakpad_googletest_includes.h" 1.42 +#include "common/test_assembler.h" 1.43 +#include "common/using_std_string.h" 1.44 +#include "google_breakpad/common/minidump_format.h" 1.45 +#include "google_breakpad/processor/basic_source_line_resolver.h" 1.46 +#include "google_breakpad/processor/call_stack.h" 1.47 +#include "google_breakpad/processor/code_module.h" 1.48 +#include "google_breakpad/processor/source_line_resolver_interface.h" 1.49 +#include "google_breakpad/processor/stack_frame_cpu.h" 1.50 +#include "processor/stackwalker_unittest_utils.h" 1.51 +#include "processor/stackwalker_arm.h" 1.52 +#include "processor/windows_frame_info.h" 1.53 + 1.54 +using google_breakpad::BasicSourceLineResolver; 1.55 +using google_breakpad::CallStack; 1.56 +using google_breakpad::CodeModule; 1.57 +using google_breakpad::StackFrameSymbolizer; 1.58 +using google_breakpad::StackFrame; 1.59 +using google_breakpad::StackFrameARM; 1.60 +using google_breakpad::StackwalkerARM; 1.61 +using google_breakpad::SystemInfo; 1.62 +using google_breakpad::WindowsFrameInfo; 1.63 +using google_breakpad::test_assembler::kLittleEndian; 1.64 +using google_breakpad::test_assembler::Label; 1.65 +using google_breakpad::test_assembler::Section; 1.66 +using std::vector; 1.67 +using testing::_; 1.68 +using testing::Return; 1.69 +using testing::SetArgumentPointee; 1.70 +using testing::Test; 1.71 + 1.72 +class StackwalkerARMFixture { 1.73 + public: 1.74 + StackwalkerARMFixture() 1.75 + : stack_section(kLittleEndian), 1.76 + // Give the two modules reasonable standard locations and names 1.77 + // for tests to play with. 1.78 + module1(0x40000000, 0x10000, "module1", "version1"), 1.79 + module2(0x50000000, 0x10000, "module2", "version2") { 1.80 + // Identify the system as a Linux system. 1.81 + system_info.os = "Linux"; 1.82 + system_info.os_short = "linux"; 1.83 + system_info.os_version = "Lugubrious Labrador"; 1.84 + system_info.cpu = "arm"; 1.85 + system_info.cpu_info = ""; 1.86 + 1.87 + // Put distinctive values in the raw CPU context. 1.88 + BrandContext(&raw_context); 1.89 + 1.90 + // Create some modules with some stock debugging information. 1.91 + modules.Add(&module1); 1.92 + modules.Add(&module2); 1.93 + 1.94 + // By default, none of the modules have symbol info; call 1.95 + // SetModuleSymbols to override this. 1.96 + EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _)) 1.97 + .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); 1.98 + } 1.99 + 1.100 + // Set the Breakpad symbol information that supplier should return for 1.101 + // MODULE to INFO. 1.102 + void SetModuleSymbols(MockCodeModule *module, const string &info) { 1.103 + char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info); 1.104 + EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _)) 1.105 + .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), 1.106 + Return(MockSymbolSupplier::FOUND))); 1.107 + } 1.108 + 1.109 + // Populate stack_region with the contents of stack_section. Use 1.110 + // stack_section.start() as the region's starting address. 1.111 + void RegionFromSection() { 1.112 + string contents; 1.113 + ASSERT_TRUE(stack_section.GetContents(&contents)); 1.114 + stack_region.Init(stack_section.start().Value(), contents); 1.115 + } 1.116 + 1.117 + // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. 1.118 + void BrandContext(MDRawContextARM *raw_context) { 1.119 + uint8_t x = 173; 1.120 + for (size_t i = 0; i < sizeof(*raw_context); i++) 1.121 + reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17); 1.122 + } 1.123 + 1.124 + SystemInfo system_info; 1.125 + MDRawContextARM raw_context; 1.126 + Section stack_section; 1.127 + MockMemoryRegion stack_region; 1.128 + MockCodeModule module1; 1.129 + MockCodeModule module2; 1.130 + MockCodeModules modules; 1.131 + MockSymbolSupplier supplier; 1.132 + BasicSourceLineResolver resolver; 1.133 + CallStack call_stack; 1.134 + const vector<StackFrame *> *frames; 1.135 +}; 1.136 + 1.137 +class SanityCheck: public StackwalkerARMFixture, public Test { }; 1.138 + 1.139 +TEST_F(SanityCheck, NoResolver) { 1.140 + // Since we have no call frame information, and all unwinding 1.141 + // requires call frame information, the stack walk will end after 1.142 + // the first frame. 1.143 + StackFrameSymbolizer frame_symbolizer(NULL, NULL); 1.144 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.145 + &frame_symbolizer); 1.146 + // This should succeed even without a resolver or supplier. 1.147 + vector<const CodeModule*> modules_without_symbols; 1.148 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.149 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.150 + frames = call_stack.frames(); 1.151 + ASSERT_EQ(1U, frames->size()); 1.152 + StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0)); 1.153 + // Check that the values from the original raw context made it 1.154 + // through to the context in the stack frame. 1.155 + EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 1.156 +} 1.157 + 1.158 +class GetContextFrame: public StackwalkerARMFixture, public Test { }; 1.159 + 1.160 +TEST_F(GetContextFrame, Simple) { 1.161 + // Since we have no call frame information, and all unwinding 1.162 + // requires call frame information, the stack walk will end after 1.163 + // the first frame. 1.164 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.165 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.166 + &frame_symbolizer); 1.167 + vector<const CodeModule*> modules_without_symbols; 1.168 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.169 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.170 + frames = call_stack.frames(); 1.171 + ASSERT_EQ(1U, frames->size()); 1.172 + StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0)); 1.173 + // Check that the values from the original raw context made it 1.174 + // through to the context in the stack frame. 1.175 + EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 1.176 +} 1.177 + 1.178 +// The stackwalker should be able to produce the context frame even 1.179 +// without stack memory present. 1.180 +TEST_F(GetContextFrame, NoStackMemory) { 1.181 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.182 + StackwalkerARM walker(&system_info, &raw_context, -1, NULL, &modules, 1.183 + &frame_symbolizer); 1.184 + vector<const CodeModule*> modules_without_symbols; 1.185 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.186 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.187 + frames = call_stack.frames(); 1.188 + ASSERT_EQ(1U, frames->size()); 1.189 + StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0)); 1.190 + // Check that the values from the original raw context made it 1.191 + // through to the context in the stack frame. 1.192 + EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 1.193 +} 1.194 + 1.195 +class GetCallerFrame: public StackwalkerARMFixture, public Test { }; 1.196 + 1.197 +TEST_F(GetCallerFrame, ScanWithoutSymbols) { 1.198 + // When the stack walker resorts to scanning the stack, 1.199 + // only addresses located within loaded modules are 1.200 + // considered valid return addresses. 1.201 + // Force scanning through three frames to ensure that the 1.202 + // stack pointer is set properly in scan-recovered frames. 1.203 + stack_section.start() = 0x80000000; 1.204 + uint32_t return_address1 = 0x50000100; 1.205 + uint32_t return_address2 = 0x50000900; 1.206 + Label frame1_sp, frame2_sp; 1.207 + stack_section 1.208 + // frame 0 1.209 + .Append(16, 0) // space 1.210 + 1.211 + .D32(0x40090000) // junk that's not 1.212 + .D32(0x60000000) // a return address 1.213 + 1.214 + .D32(return_address1) // actual return address 1.215 + // frame 1 1.216 + .Mark(&frame1_sp) 1.217 + .Append(16, 0) // space 1.218 + 1.219 + .D32(0xF0000000) // more junk 1.220 + .D32(0x0000000D) 1.221 + 1.222 + .D32(return_address2) // actual return address 1.223 + // frame 2 1.224 + .Mark(&frame2_sp) 1.225 + .Append(32, 0); // end of stack 1.226 + RegionFromSection(); 1.227 + 1.228 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; 1.229 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); 1.230 + 1.231 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.232 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.233 + &frame_symbolizer); 1.234 + vector<const CodeModule*> modules_without_symbols; 1.235 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.236 + ASSERT_EQ(2U, modules_without_symbols.size()); 1.237 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.238 + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); 1.239 + frames = call_stack.frames(); 1.240 + ASSERT_EQ(3U, frames->size()); 1.241 + 1.242 + StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); 1.243 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.244 + ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); 1.245 + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); 1.246 + 1.247 + StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); 1.248 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 1.249 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.250 + StackFrameARM::CONTEXT_VALID_SP), 1.251 + frame1->context_validity); 1.252 + EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.253 + EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.254 + 1.255 + StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2)); 1.256 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust); 1.257 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.258 + StackFrameARM::CONTEXT_VALID_SP), 1.259 + frame2->context_validity); 1.260 + EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.261 + EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.262 +} 1.263 + 1.264 +TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { 1.265 + // During stack scanning, if a potential return address 1.266 + // is located within a loaded module that has symbols, 1.267 + // it is only considered a valid return address if it 1.268 + // lies within a function's bounds. 1.269 + stack_section.start() = 0x80000000; 1.270 + uint32_t return_address = 0x50000200; 1.271 + Label frame1_sp; 1.272 + 1.273 + stack_section 1.274 + // frame 0 1.275 + .Append(16, 0) // space 1.276 + 1.277 + .D32(0x40090000) // junk that's not 1.278 + .D32(0x60000000) // a return address 1.279 + 1.280 + .D32(0x40001000) // a couple of plausible addresses 1.281 + .D32(0x5000F000) // that are not within functions 1.282 + 1.283 + .D32(return_address) // actual return address 1.284 + // frame 1 1.285 + .Mark(&frame1_sp) 1.286 + .Append(32, 0); // end of stack 1.287 + RegionFromSection(); 1.288 + 1.289 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40000200; 1.290 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); 1.291 + 1.292 + SetModuleSymbols(&module1, 1.293 + // The youngest frame's function. 1.294 + "FUNC 100 400 10 monotreme\n"); 1.295 + SetModuleSymbols(&module2, 1.296 + // The calling frame's function. 1.297 + "FUNC 100 400 10 marsupial\n"); 1.298 + 1.299 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.300 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.301 + &frame_symbolizer); 1.302 + vector<const CodeModule*> modules_without_symbols; 1.303 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.304 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.305 + frames = call_stack.frames(); 1.306 + ASSERT_EQ(2U, frames->size()); 1.307 + 1.308 + StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); 1.309 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.310 + ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); 1.311 + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); 1.312 + EXPECT_EQ("monotreme", frame0->function_name); 1.313 + EXPECT_EQ(0x40000100U, frame0->function_base); 1.314 + 1.315 + StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); 1.316 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 1.317 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.318 + StackFrameARM::CONTEXT_VALID_SP), 1.319 + frame1->context_validity); 1.320 + EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.321 + EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.322 + EXPECT_EQ("marsupial", frame1->function_name); 1.323 + EXPECT_EQ(0x50000100U, frame1->function_base); 1.324 +} 1.325 + 1.326 +TEST_F(GetCallerFrame, ScanFirstFrame) { 1.327 + // If the stackwalker resorts to stack scanning, it will scan much 1.328 + // farther to find the caller of the context frame. 1.329 + stack_section.start() = 0x80000000; 1.330 + uint32_t return_address1 = 0x50000100; 1.331 + uint32_t return_address2 = 0x50000900; 1.332 + Label frame1_sp, frame2_sp; 1.333 + stack_section 1.334 + // frame 0 1.335 + .Append(32, 0) // space 1.336 + 1.337 + .D32(0x40090000) // junk that's not 1.338 + .D32(0x60000000) // a return address 1.339 + 1.340 + .Append(96, 0) // more space 1.341 + 1.342 + .D32(return_address1) // actual return address 1.343 + // frame 1 1.344 + .Mark(&frame1_sp) 1.345 + .Append(32, 0) // space 1.346 + 1.347 + .D32(0xF0000000) // more junk 1.348 + .D32(0x0000000D) 1.349 + 1.350 + .Append(96, 0) // more space 1.351 + 1.352 + .D32(return_address2) // actual return address 1.353 + // (won't be found) 1.354 + // frame 2 1.355 + .Mark(&frame2_sp) 1.356 + .Append(32, 0); // end of stack 1.357 + RegionFromSection(); 1.358 + 1.359 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; 1.360 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); 1.361 + 1.362 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.363 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.364 + &frame_symbolizer); 1.365 + vector<const CodeModule*> modules_without_symbols; 1.366 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.367 + ASSERT_EQ(2U, modules_without_symbols.size()); 1.368 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.369 + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); 1.370 + frames = call_stack.frames(); 1.371 + ASSERT_EQ(2U, frames->size()); 1.372 + 1.373 + StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); 1.374 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.375 + ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); 1.376 + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); 1.377 + 1.378 + StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); 1.379 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 1.380 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.381 + StackFrameARM::CONTEXT_VALID_SP), 1.382 + frame1->context_validity); 1.383 + EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.384 + EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.385 +} 1.386 + 1.387 +struct CFIFixture: public StackwalkerARMFixture { 1.388 + CFIFixture() { 1.389 + // Provide a bunch of STACK CFI records; we'll walk to the caller 1.390 + // from every point in this series, expecting to find the same set 1.391 + // of register values. 1.392 + SetModuleSymbols(&module1, 1.393 + // The youngest frame's function. 1.394 + "FUNC 4000 1000 10 enchiridion\n" 1.395 + // Initially, nothing has been pushed on the stack, 1.396 + // and the return address is still in the link register. 1.397 + "STACK CFI INIT 4000 100 .cfa: sp .ra: lr\n" 1.398 + // Push r4, the frame pointer, and the link register. 1.399 + "STACK CFI 4001 .cfa: sp 12 + r4: .cfa 12 - ^" 1.400 + " r11: .cfa 8 - ^ .ra: .cfa 4 - ^\n" 1.401 + // Save r4..r7 in r0..r3: verify that we populate 1.402 + // the youngest frame with all the values we have. 1.403 + "STACK CFI 4002 r4: r0 r5: r1 r6: r2 r7: r3\n" 1.404 + // Restore r4..r7. Save the non-callee-saves register r1. 1.405 + "STACK CFI 4003 .cfa: sp 16 + r1: .cfa 16 - ^" 1.406 + " r4: r4 r5: r5 r6: r6 r7: r7\n" 1.407 + // Move the .cfa back four bytes, to point at the return 1.408 + // address, and restore the sp explicitly. 1.409 + "STACK CFI 4005 .cfa: sp 12 + r1: .cfa 12 - ^" 1.410 + " r11: .cfa 4 - ^ .ra: .cfa ^ sp: .cfa 4 +\n" 1.411 + // Recover the PC explicitly from a new stack slot; 1.412 + // provide garbage for the .ra. 1.413 + "STACK CFI 4006 .cfa: sp 16 + pc: .cfa 16 - ^\n" 1.414 + 1.415 + // The calling function. 1.416 + "FUNC 5000 1000 10 epictetus\n" 1.417 + // Mark it as end of stack. 1.418 + "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n" 1.419 + 1.420 + // A function whose CFI makes the stack pointer 1.421 + // go backwards. 1.422 + "FUNC 6000 1000 20 palinal\n" 1.423 + "STACK CFI INIT 6000 1000 .cfa: sp 4 - .ra: lr\n" 1.424 + 1.425 + // A function with CFI expressions that can't be 1.426 + // evaluated. 1.427 + "FUNC 7000 1000 20 rhetorical\n" 1.428 + "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"); 1.429 + 1.430 + // Provide some distinctive values for the caller's registers. 1.431 + expected.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; 1.432 + expected.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; 1.433 + expected.iregs[4] = 0xb5d55e68; 1.434 + expected.iregs[5] = 0xebd134f3; 1.435 + expected.iregs[6] = 0xa31e74bc; 1.436 + expected.iregs[7] = 0x2dcb16b3; 1.437 + expected.iregs[8] = 0x2ada2137; 1.438 + expected.iregs[9] = 0xbbbb557d; 1.439 + expected.iregs[10] = 0x48bf8ca7; 1.440 + expected.iregs[MD_CONTEXT_ARM_REG_FP] = 0x8112e110; 1.441 + 1.442 + // Expect CFI to recover all callee-saves registers. Since CFI is the 1.443 + // only stack frame construction technique we have, aside from the 1.444 + // context frame itself, there's no way for us to have a set of valid 1.445 + // registers smaller than this. 1.446 + expected_validity = (StackFrameARM::CONTEXT_VALID_PC | 1.447 + StackFrameARM::CONTEXT_VALID_SP | 1.448 + StackFrameARM::CONTEXT_VALID_R4 | 1.449 + StackFrameARM::CONTEXT_VALID_R5 | 1.450 + StackFrameARM::CONTEXT_VALID_R6 | 1.451 + StackFrameARM::CONTEXT_VALID_R7 | 1.452 + StackFrameARM::CONTEXT_VALID_R8 | 1.453 + StackFrameARM::CONTEXT_VALID_R9 | 1.454 + StackFrameARM::CONTEXT_VALID_R10 | 1.455 + StackFrameARM::CONTEXT_VALID_FP); 1.456 + 1.457 + // By default, context frames provide all registers, as normal. 1.458 + context_frame_validity = StackFrameARM::CONTEXT_VALID_ALL; 1.459 + 1.460 + // By default, registers are unchanged. 1.461 + raw_context = expected; 1.462 + } 1.463 + 1.464 + // Walk the stack, using stack_section as the contents of the stack 1.465 + // and raw_context as the current register values. (Set the stack 1.466 + // pointer to the stack's starting address.) Expect two stack 1.467 + // frames; in the older frame, expect the callee-saves registers to 1.468 + // have values matching those in 'expected'. 1.469 + void CheckWalk() { 1.470 + RegionFromSection(); 1.471 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); 1.472 + 1.473 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.474 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, 1.475 + &modules, &frame_symbolizer); 1.476 + walker.SetContextFrameValidity(context_frame_validity); 1.477 + vector<const CodeModule*> modules_without_symbols; 1.478 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.479 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.480 + frames = call_stack.frames(); 1.481 + ASSERT_EQ(2U, frames->size()); 1.482 + 1.483 + StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); 1.484 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.485 + ASSERT_EQ(context_frame_validity, frame0->context_validity); 1.486 + EXPECT_EQ("enchiridion", frame0->function_name); 1.487 + EXPECT_EQ(0x40004000U, frame0->function_base); 1.488 + 1.489 + StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); 1.490 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.491 + ASSERT_EQ(expected_validity, frame1->context_validity); 1.492 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R1) 1.493 + EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]); 1.494 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R4) 1.495 + EXPECT_EQ(expected.iregs[4], frame1->context.iregs[4]); 1.496 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R5) 1.497 + EXPECT_EQ(expected.iregs[5], frame1->context.iregs[5]); 1.498 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R6) 1.499 + EXPECT_EQ(expected.iregs[6], frame1->context.iregs[6]); 1.500 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R7) 1.501 + EXPECT_EQ(expected.iregs[7], frame1->context.iregs[7]); 1.502 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R8) 1.503 + EXPECT_EQ(expected.iregs[8], frame1->context.iregs[8]); 1.504 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R9) 1.505 + EXPECT_EQ(expected.iregs[9], frame1->context.iregs[9]); 1.506 + if (expected_validity & StackFrameARM::CONTEXT_VALID_R10) 1.507 + EXPECT_EQ(expected.iregs[10], frame1->context.iregs[10]); 1.508 + if (expected_validity & StackFrameARM::CONTEXT_VALID_FP) 1.509 + EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_FP], 1.510 + frame1->context.iregs[MD_CONTEXT_ARM_REG_FP]); 1.511 + 1.512 + // We would never have gotten a frame in the first place if the SP 1.513 + // and PC weren't valid or ->instruction weren't set. 1.514 + EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_SP], 1.515 + frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.516 + EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_PC], 1.517 + frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.518 + EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_PC], 1.519 + frame1->instruction + 2); 1.520 + EXPECT_EQ("epictetus", frame1->function_name); 1.521 + } 1.522 + 1.523 + // The values we expect to find for the caller's registers. 1.524 + MDRawContextARM expected; 1.525 + 1.526 + // The validity mask for expected. 1.527 + int expected_validity; 1.528 + 1.529 + // The validity mask to impose on the context frame. 1.530 + int context_frame_validity; 1.531 +}; 1.532 + 1.533 +class CFI: public CFIFixture, public Test { }; 1.534 + 1.535 +TEST_F(CFI, At4000) { 1.536 + stack_section.start() = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.537 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004000; 1.538 + raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510; 1.539 + CheckWalk(); 1.540 +} 1.541 + 1.542 +TEST_F(CFI, At4001) { 1.543 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.544 + stack_section 1.545 + .D32(0xb5d55e68) // saved r4 1.546 + .D32(0x8112e110) // saved fp 1.547 + .D32(0x40005510) // return address 1.548 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.549 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004001; 1.550 + raw_context.iregs[4] = 0x635adc9f; // distinct callee r4 1.551 + raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp 1.552 + CheckWalk(); 1.553 +} 1.554 + 1.555 +// As above, but unwind from a context that has only the PC and SP. 1.556 +TEST_F(CFI, At4001LimitedValidity) { 1.557 + context_frame_validity = 1.558 + StackFrameARM::CONTEXT_VALID_PC | StackFrameARM::CONTEXT_VALID_SP; 1.559 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004001; 1.560 + raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp 1.561 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.562 + stack_section 1.563 + .D32(0xb5d55e68) // saved r4 1.564 + .D32(0x8112e110) // saved fp 1.565 + .D32(0x40005510) // return address 1.566 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.567 + expected_validity = (StackFrameARM::CONTEXT_VALID_PC 1.568 + | StackFrameARM::CONTEXT_VALID_SP 1.569 + | StackFrameARM::CONTEXT_VALID_FP 1.570 + | StackFrameARM::CONTEXT_VALID_R4); 1.571 + CheckWalk(); 1.572 +} 1.573 + 1.574 +TEST_F(CFI, At4002) { 1.575 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.576 + stack_section 1.577 + .D32(0xfb81ff3d) // no longer saved r4 1.578 + .D32(0x8112e110) // saved fp 1.579 + .D32(0x40005510) // return address 1.580 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.581 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004002; 1.582 + raw_context.iregs[0] = 0xb5d55e68; // saved r4 1.583 + raw_context.iregs[1] = 0xebd134f3; // saved r5 1.584 + raw_context.iregs[2] = 0xa31e74bc; // saved r6 1.585 + raw_context.iregs[3] = 0x2dcb16b3; // saved r7 1.586 + raw_context.iregs[4] = 0xfdd35466; // distinct callee r4 1.587 + raw_context.iregs[5] = 0xf18c946c; // distinct callee r5 1.588 + raw_context.iregs[6] = 0xac2079e8; // distinct callee r6 1.589 + raw_context.iregs[7] = 0xa449829f; // distinct callee r7 1.590 + raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp 1.591 + CheckWalk(); 1.592 +} 1.593 + 1.594 +TEST_F(CFI, At4003) { 1.595 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.596 + stack_section 1.597 + .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) 1.598 + .D32(0xcb78040e) // no longer saved r4 1.599 + .D32(0x8112e110) // saved fp 1.600 + .D32(0x40005510) // return address 1.601 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.602 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004003; 1.603 + raw_context.iregs[1] = 0xfb756319; // distinct callee r1 1.604 + raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0x0a2857ea; // distinct callee fp 1.605 + expected.iregs[1] = 0x48c8dd5a; // caller's r1 1.606 + expected_validity |= StackFrameARM::CONTEXT_VALID_R1; 1.607 + CheckWalk(); 1.608 +} 1.609 + 1.610 +// We have no new rule at module offset 0x4004, so the results here should 1.611 +// be the same as those at module offset 0x4003. 1.612 +TEST_F(CFI, At4004) { 1.613 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.614 + stack_section 1.615 + .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) 1.616 + .D32(0xcb78040e) // no longer saved r4 1.617 + .D32(0x8112e110) // saved fp 1.618 + .D32(0x40005510) // return address 1.619 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.620 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004004; 1.621 + raw_context.iregs[1] = 0xfb756319; // distinct callee r1 1.622 + expected.iregs[1] = 0x48c8dd5a; // caller's r1 1.623 + expected_validity |= StackFrameARM::CONTEXT_VALID_R1; 1.624 + CheckWalk(); 1.625 +} 1.626 + 1.627 +// Here we move the .cfa, but provide an explicit rule to recover the SP, 1.628 +// so again there should be no change in the registers recovered. 1.629 +TEST_F(CFI, At4005) { 1.630 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.631 + stack_section 1.632 + .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) 1.633 + .D32(0xf013f841) // no longer saved r4 1.634 + .D32(0x8112e110) // saved fp 1.635 + .D32(0x40005510) // return address 1.636 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.637 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004005; 1.638 + raw_context.iregs[1] = 0xfb756319; // distinct callee r1 1.639 + expected.iregs[1] = 0x48c8dd5a; // caller's r1 1.640 + expected_validity |= StackFrameARM::CONTEXT_VALID_R1; 1.641 + CheckWalk(); 1.642 +} 1.643 + 1.644 +// Here we provide an explicit rule for the PC, and have the saved .ra be 1.645 +// bogus. 1.646 +TEST_F(CFI, At4006) { 1.647 + Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; 1.648 + stack_section 1.649 + .D32(0x40005510) // saved pc 1.650 + .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) 1.651 + .D32(0xf013f841) // no longer saved r4 1.652 + .D32(0x8112e110) // saved fp 1.653 + .D32(0xf8d15783) // .ra rule recovers this, which is garbage 1.654 + .Mark(&frame1_sp); // This effectively sets stack_section.start(). 1.655 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004006; 1.656 + raw_context.iregs[1] = 0xfb756319; // callee's r1, different from caller's 1.657 + expected.iregs[1] = 0x48c8dd5a; // caller's r1 1.658 + expected_validity |= StackFrameARM::CONTEXT_VALID_R1; 1.659 + CheckWalk(); 1.660 +} 1.661 + 1.662 +// Check that we reject rules that would cause the stack pointer to 1.663 +// move in the wrong direction. 1.664 +TEST_F(CFI, RejectBackwards) { 1.665 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40006000; 1.666 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; 1.667 + raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510; 1.668 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.669 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.670 + &frame_symbolizer); 1.671 + vector<const CodeModule*> modules_without_symbols; 1.672 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.673 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.674 + frames = call_stack.frames(); 1.675 + ASSERT_EQ(1U, frames->size()); 1.676 +} 1.677 + 1.678 +// Check that we reject rules whose expressions' evaluation fails. 1.679 +TEST_F(CFI, RejectBadExpressions) { 1.680 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40007000; 1.681 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; 1.682 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.683 + StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, 1.684 + &frame_symbolizer); 1.685 + vector<const CodeModule*> modules_without_symbols; 1.686 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.687 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.688 + frames = call_stack.frames(); 1.689 + ASSERT_EQ(1U, frames->size()); 1.690 +} 1.691 + 1.692 +class StackwalkerARMFixtureIOS : public StackwalkerARMFixture { 1.693 + public: 1.694 + StackwalkerARMFixtureIOS() { 1.695 + system_info.os = "iOS"; 1.696 + system_info.os_short = "ios"; 1.697 + } 1.698 +}; 1.699 + 1.700 +class GetFramesByFramePointer: public StackwalkerARMFixtureIOS, public Test { }; 1.701 + 1.702 +TEST_F(GetFramesByFramePointer, OnlyFramePointer) { 1.703 + stack_section.start() = 0x80000000; 1.704 + uint32_t return_address1 = 0x50000100; 1.705 + uint32_t return_address2 = 0x50000900; 1.706 + Label frame1_sp, frame2_sp; 1.707 + Label frame1_fp, frame2_fp; 1.708 + stack_section 1.709 + // frame 0 1.710 + .Append(32, 0) // Whatever values on the stack. 1.711 + .D32(0x0000000D) // junk that's not 1.712 + .D32(0xF0000000) // a return address. 1.713 + 1.714 + .Mark(&frame1_fp) // Next fp will point to the next value. 1.715 + .D32(frame2_fp) // Save current frame pointer. 1.716 + .D32(return_address2) // Save current link register. 1.717 + .Mark(&frame1_sp) 1.718 + 1.719 + // frame 1 1.720 + .Append(32, 0) // Whatever values on the stack. 1.721 + .D32(0x0000000D) // junk that's not 1.722 + .D32(0xF0000000) // a return address. 1.723 + 1.724 + .Mark(&frame2_fp) 1.725 + .D32(0) 1.726 + .D32(0) 1.727 + .Mark(&frame2_sp) 1.728 + 1.729 + // frame 2 1.730 + .Append(32, 0) // Whatever values on the stack. 1.731 + .D32(0x0000000D) // junk that's not 1.732 + .D32(0xF0000000); // a return address. 1.733 + RegionFromSection(); 1.734 + 1.735 + 1.736 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; 1.737 + raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = return_address1; 1.738 + raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value(); 1.739 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); 1.740 + 1.741 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.742 + StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, 1.743 + &stack_region, &modules, &frame_symbolizer); 1.744 + 1.745 + vector<const CodeModule*> modules_without_symbols; 1.746 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.747 + ASSERT_EQ(2U, modules_without_symbols.size()); 1.748 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.749 + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); 1.750 + frames = call_stack.frames(); 1.751 + ASSERT_EQ(3U, frames->size()); 1.752 + 1.753 + StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); 1.754 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.755 + ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); 1.756 + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); 1.757 + 1.758 + StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); 1.759 + EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 1.760 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.761 + StackFrameARM::CONTEXT_VALID_LR | 1.762 + StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | 1.763 + StackFrameARM::CONTEXT_VALID_SP), 1.764 + frame1->context_validity); 1.765 + EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.766 + EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM_REG_LR]); 1.767 + EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.768 + EXPECT_EQ(frame2_fp.Value(), 1.769 + frame1->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); 1.770 + 1.771 + StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2)); 1.772 + EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust); 1.773 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.774 + StackFrameARM::CONTEXT_VALID_LR | 1.775 + StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | 1.776 + StackFrameARM::CONTEXT_VALID_SP), 1.777 + frame2->context_validity); 1.778 + EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.779 + EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_LR]); 1.780 + EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.781 + EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); 1.782 +} 1.783 + 1.784 +TEST_F(GetFramesByFramePointer, FramePointerAndCFI) { 1.785 + // Provide the standatd STACK CFI records that is obtained when exmining an 1.786 + // executable produced by XCode. 1.787 + SetModuleSymbols(&module1, 1.788 + // Adding a function in CFI. 1.789 + "FUNC 4000 1000 10 enchiridion\n" 1.790 + 1.791 + "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: lr\n" 1.792 + "STACK CFI 4001 .cfa: sp 8 + .ra: .cfa -4 + ^" 1.793 + " r7: .cfa -8 + ^\n" 1.794 + "STACK CFI 4002 .cfa: r7 8 +\n" 1.795 + ); 1.796 + 1.797 + stack_section.start() = 0x80000000; 1.798 + uint32_t return_address1 = 0x40004010; 1.799 + uint32_t return_address2 = 0x50000900; 1.800 + Label frame1_sp, frame2_sp; 1.801 + Label frame1_fp, frame2_fp; 1.802 + stack_section 1.803 + // frame 0 1.804 + .Append(32, 0) // Whatever values on the stack. 1.805 + .D32(0x0000000D) // junk that's not 1.806 + .D32(0xF0000000) // a return address. 1.807 + 1.808 + .Mark(&frame1_fp) // Next fp will point to the next value. 1.809 + .D32(frame2_fp) // Save current frame pointer. 1.810 + .D32(return_address2) // Save current link register. 1.811 + .Mark(&frame1_sp) 1.812 + 1.813 + // frame 1 1.814 + .Append(32, 0) // Whatever values on the stack. 1.815 + .D32(0x0000000D) // junk that's not 1.816 + .D32(0xF0000000) // a return address. 1.817 + 1.818 + .Mark(&frame2_fp) 1.819 + .D32(0) 1.820 + .D32(0) 1.821 + .Mark(&frame2_sp) 1.822 + 1.823 + // frame 2 1.824 + .Append(32, 0) // Whatever values on the stack. 1.825 + .D32(0x0000000D) // junk that's not 1.826 + .D32(0xF0000000); // a return address. 1.827 + RegionFromSection(); 1.828 + 1.829 + 1.830 + raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x50000400; 1.831 + raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = return_address1; 1.832 + raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value(); 1.833 + raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); 1.834 + 1.835 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.836 + StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, 1.837 + &stack_region, &modules, &frame_symbolizer); 1.838 + 1.839 + vector<const CodeModule*> modules_without_symbols; 1.840 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.841 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.842 + ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); 1.843 + frames = call_stack.frames(); 1.844 + ASSERT_EQ(3U, frames->size()); 1.845 + 1.846 + StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); 1.847 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.848 + ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); 1.849 + EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); 1.850 + 1.851 + StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); 1.852 + EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 1.853 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.854 + StackFrameARM::CONTEXT_VALID_LR | 1.855 + StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | 1.856 + StackFrameARM::CONTEXT_VALID_SP), 1.857 + frame1->context_validity); 1.858 + EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.859 + EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM_REG_LR]); 1.860 + EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.861 + EXPECT_EQ(frame2_fp.Value(), 1.862 + frame1->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); 1.863 + EXPECT_EQ("enchiridion", frame1->function_name); 1.864 + EXPECT_EQ(0x40004000U, frame1->function_base); 1.865 + 1.866 + 1.867 + StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2)); 1.868 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 1.869 + ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | 1.870 + StackFrameARM::CONTEXT_VALID_LR | 1.871 + StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | 1.872 + StackFrameARM::CONTEXT_VALID_SP), 1.873 + frame2->context_validity); 1.874 + EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]); 1.875 + EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_LR]); 1.876 + EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]); 1.877 + EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); 1.878 +}