1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1551 @@ 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_x86_unittest.cc: Unit tests for StackwalkerX86 class. 1.36 + 1.37 +#include <string> 1.38 +#include <vector> 1.39 + 1.40 +#include "breakpad_googletest_includes.h" 1.41 +#include "common/test_assembler.h" 1.42 +#include "common/using_std_string.h" 1.43 +#include "google_breakpad/common/minidump_format.h" 1.44 +#include "google_breakpad/processor/basic_source_line_resolver.h" 1.45 +#include "google_breakpad/processor/call_stack.h" 1.46 +#include "google_breakpad/processor/code_module.h" 1.47 +#include "google_breakpad/processor/source_line_resolver_interface.h" 1.48 +#include "google_breakpad/processor/stack_frame_cpu.h" 1.49 +#include "processor/stackwalker_unittest_utils.h" 1.50 +#include "processor/stackwalker_x86.h" 1.51 +#include "processor/windows_frame_info.h" 1.52 + 1.53 +using google_breakpad::BasicSourceLineResolver; 1.54 +using google_breakpad::CallStack; 1.55 +using google_breakpad::CodeModule; 1.56 +using google_breakpad::StackFrameSymbolizer; 1.57 +using google_breakpad::StackFrame; 1.58 +using google_breakpad::StackFrameX86; 1.59 +using google_breakpad::StackwalkerX86; 1.60 +using google_breakpad::SystemInfo; 1.61 +using google_breakpad::WindowsFrameInfo; 1.62 +using google_breakpad::test_assembler::kLittleEndian; 1.63 +using google_breakpad::test_assembler::Label; 1.64 +using google_breakpad::test_assembler::Section; 1.65 +using std::vector; 1.66 +using testing::_; 1.67 +using testing::Return; 1.68 +using testing::SetArgumentPointee; 1.69 +using testing::Test; 1.70 + 1.71 +class StackwalkerX86Fixture { 1.72 + public: 1.73 + StackwalkerX86Fixture() 1.74 + : stack_section(kLittleEndian), 1.75 + // Give the two modules reasonable standard locations and names 1.76 + // for tests to play with. 1.77 + module1(0x40000000, 0x10000, "module1", "version1"), 1.78 + module2(0x50000000, 0x10000, "module2", "version2"), 1.79 + module3(0x771d0000, 0x180000, "module3", "version3"), 1.80 + module4(0x75f90000, 0x46000, "module4", "version4"), 1.81 + module5(0x75730000, 0x110000, "module5", "version5"), 1.82 + module6(0x647f0000, 0x1ba8000, "module6", "version6") { 1.83 + // Identify the system as a Linux system. 1.84 + system_info.os = "Linux"; 1.85 + system_info.os_short = "linux"; 1.86 + system_info.os_version = "Salacious Skink"; 1.87 + system_info.cpu = "x86"; 1.88 + system_info.cpu_info = ""; 1.89 + 1.90 + // Put distinctive values in the raw CPU context. 1.91 + BrandContext(&raw_context); 1.92 + 1.93 + // Create some modules with some stock debugging information. 1.94 + modules.Add(&module1); 1.95 + modules.Add(&module2); 1.96 + modules.Add(&module3); 1.97 + modules.Add(&module4); 1.98 + modules.Add(&module5); 1.99 + modules.Add(&module6); 1.100 + 1.101 + // By default, none of the modules have symbol info; call 1.102 + // SetModuleSymbols to override this. 1.103 + EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _)) 1.104 + .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); 1.105 + } 1.106 + 1.107 + // Set the Breakpad symbol information that supplier should return for 1.108 + // MODULE to INFO. 1.109 + void SetModuleSymbols(MockCodeModule *module, const string &info) { 1.110 + char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info); 1.111 + EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _)) 1.112 + .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), 1.113 + Return(MockSymbolSupplier::FOUND))); 1.114 + } 1.115 + 1.116 + // Populate stack_region with the contents of stack_section. Use 1.117 + // stack_section.start() as the region's starting address. 1.118 + void RegionFromSection() { 1.119 + string contents; 1.120 + ASSERT_TRUE(stack_section.GetContents(&contents)); 1.121 + stack_region.Init(stack_section.start().Value(), contents); 1.122 + } 1.123 + 1.124 + // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. 1.125 + void BrandContext(MDRawContextX86 *raw_context) { 1.126 + uint8_t x = 173; 1.127 + for (size_t i = 0; i < sizeof(*raw_context); i++) 1.128 + reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17); 1.129 + } 1.130 + 1.131 + SystemInfo system_info; 1.132 + MDRawContextX86 raw_context; 1.133 + Section stack_section; 1.134 + MockMemoryRegion stack_region; 1.135 + MockCodeModule module1; 1.136 + MockCodeModule module2; 1.137 + MockCodeModule module3; 1.138 + MockCodeModule module4; 1.139 + MockCodeModule module5; 1.140 + MockCodeModule module6; 1.141 + MockCodeModules modules; 1.142 + MockSymbolSupplier supplier; 1.143 + BasicSourceLineResolver resolver; 1.144 + CallStack call_stack; 1.145 + const vector<StackFrame *> *frames; 1.146 +}; 1.147 + 1.148 +class SanityCheck: public StackwalkerX86Fixture, public Test { }; 1.149 + 1.150 +TEST_F(SanityCheck, NoResolver) { 1.151 + stack_section.start() = 0x80000000; 1.152 + stack_section.D32(0).D32(0); // end-of-stack marker 1.153 + RegionFromSection(); 1.154 + raw_context.eip = 0x40000200; 1.155 + raw_context.ebp = 0x80000000; 1.156 + 1.157 + StackFrameSymbolizer frame_symbolizer(NULL, NULL); 1.158 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.159 + &frame_symbolizer); 1.160 + // This should succeed, even without a resolver or supplier. 1.161 + vector<const CodeModule*> modules_without_symbols; 1.162 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.163 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.164 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.165 + frames = call_stack.frames(); 1.166 + StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); 1.167 + // Check that the values from the original raw context made it 1.168 + // through to the context in the stack frame. 1.169 + EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 1.170 +} 1.171 + 1.172 +class GetContextFrame: public StackwalkerX86Fixture, public Test { }; 1.173 + 1.174 +TEST_F(GetContextFrame, Simple) { 1.175 + stack_section.start() = 0x80000000; 1.176 + stack_section.D32(0).D32(0); // end-of-stack marker 1.177 + RegionFromSection(); 1.178 + raw_context.eip = 0x40000200; 1.179 + raw_context.ebp = 0x80000000; 1.180 + 1.181 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.182 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &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(1U, modules_without_symbols.size()); 1.187 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.188 + frames = call_stack.frames(); 1.189 + StackFrameX86 *frame = static_cast<StackFrameX86 *>(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 +// The stackwalker should be able to produce the context frame even 1.196 +// without stack memory present. 1.197 +TEST_F(GetContextFrame, NoStackMemory) { 1.198 + raw_context.eip = 0x40000200; 1.199 + raw_context.ebp = 0x80000000; 1.200 + 1.201 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.202 + StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules, 1.203 + &frame_symbolizer); 1.204 + vector<const CodeModule*> modules_without_symbols; 1.205 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.206 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.207 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.208 + frames = call_stack.frames(); 1.209 + StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); 1.210 + // Check that the values from the original raw context made it 1.211 + // through to the context in the stack frame. 1.212 + EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 1.213 +} 1.214 + 1.215 +class GetCallerFrame: public StackwalkerX86Fixture, public Test { }; 1.216 + 1.217 +// Walk a traditional frame. A traditional frame saves the caller's 1.218 +// %ebp just below the return address, and has its own %ebp pointing 1.219 +// at the saved %ebp. 1.220 +TEST_F(GetCallerFrame, Traditional) { 1.221 + stack_section.start() = 0x80000000; 1.222 + Label frame0_ebp, frame1_ebp; 1.223 + stack_section 1.224 + .Append(12, 0) // frame 0: space 1.225 + .Mark(&frame0_ebp) // frame 0 %ebp points here 1.226 + .D32(frame1_ebp) // frame 0: saved %ebp 1.227 + .D32(0x40008679) // frame 0: return address 1.228 + .Append(8, 0) // frame 1: space 1.229 + .Mark(&frame1_ebp) // frame 1 %ebp points here 1.230 + .D32(0) // frame 1: saved %ebp (stack end) 1.231 + .D32(0); // frame 1: return address (stack end) 1.232 + RegionFromSection(); 1.233 + raw_context.eip = 0x4000c7a5; 1.234 + raw_context.esp = stack_section.start().Value(); 1.235 + raw_context.ebp = frame0_ebp.Value(); 1.236 + 1.237 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.238 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.239 + &frame_symbolizer); 1.240 + vector<const CodeModule*> modules_without_symbols; 1.241 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.242 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.243 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.244 + frames = call_stack.frames(); 1.245 + ASSERT_EQ(2U, frames->size()); 1.246 + 1.247 + { // To avoid reusing locals by mistake 1.248 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.249 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.250 + EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.251 + EXPECT_EQ(0x4000c7a5U, frame0->instruction); 1.252 + EXPECT_EQ(0x4000c7a5U, frame0->context.eip); 1.253 + EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 1.254 + EXPECT_EQ(NULL, frame0->windows_frame_info); 1.255 + } 1.256 + 1.257 + { // To avoid reusing locals by mistake 1.258 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.259 + EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 1.260 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.261 + | StackFrameX86::CONTEXT_VALID_ESP 1.262 + | StackFrameX86::CONTEXT_VALID_EBP), 1.263 + frame1->context_validity); 1.264 + EXPECT_EQ(0x40008679U, frame1->instruction + 1); 1.265 + EXPECT_EQ(0x40008679U, frame1->context.eip); 1.266 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.267 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.268 + } 1.269 +} 1.270 + 1.271 +// Walk a traditional frame, but use a bogus %ebp value, forcing a scan 1.272 +// of the stack for something that looks like a return address. 1.273 +TEST_F(GetCallerFrame, TraditionalScan) { 1.274 + stack_section.start() = 0x80000000; 1.275 + Label frame1_ebp; 1.276 + stack_section 1.277 + // frame 0 1.278 + .D32(0xf065dc76) // locals area: 1.279 + .D32(0x46ee2167) // garbage that doesn't look like 1.280 + .D32(0xbab023ec) // a return address 1.281 + .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) 1.282 + .D32(0x4000129d) // return address 1.283 + // frame 1 1.284 + .Append(8, 0) // space 1.285 + .Mark(&frame1_ebp) // %ebp points here 1.286 + .D32(0) // saved %ebp (stack end) 1.287 + .D32(0); // return address (stack end) 1.288 + 1.289 + RegionFromSection(); 1.290 + raw_context.eip = 0x4000f49d; 1.291 + raw_context.esp = stack_section.start().Value(); 1.292 + // Make the frame pointer bogus, to make the stackwalker scan the stack 1.293 + // for something that looks like a return address. 1.294 + raw_context.ebp = 0xd43eed6e; 1.295 + 1.296 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.297 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.298 + &frame_symbolizer); 1.299 + vector<const CodeModule*> modules_without_symbols; 1.300 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.301 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.302 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.303 + frames = call_stack.frames(); 1.304 + ASSERT_EQ(2U, frames->size()); 1.305 + 1.306 + { // To avoid reusing locals by mistake 1.307 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.308 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.309 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.310 + EXPECT_EQ(0x4000f49dU, frame0->instruction); 1.311 + EXPECT_EQ(0x4000f49dU, frame0->context.eip); 1.312 + EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 1.313 + EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); 1.314 + EXPECT_EQ(NULL, frame0->windows_frame_info); 1.315 + } 1.316 + 1.317 + { // To avoid reusing locals by mistake 1.318 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.319 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 1.320 + // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 1.321 + // walker does not actually fetch the EBP after a scan (forcing the 1.322 + // next frame to be scanned as well). But let's grandfather the existing 1.323 + // behavior in for now. 1.324 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.325 + | StackFrameX86::CONTEXT_VALID_ESP 1.326 + | StackFrameX86::CONTEXT_VALID_EBP), 1.327 + frame1->context_validity); 1.328 + EXPECT_EQ(0x4000129dU, frame1->instruction + 1); 1.329 + EXPECT_EQ(0x4000129dU, frame1->context.eip); 1.330 + EXPECT_EQ(0x80000014U, frame1->context.esp); 1.331 + EXPECT_EQ(0xd43eed6eU, frame1->context.ebp); 1.332 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.333 + } 1.334 +} 1.335 + 1.336 +// Force scanning for a return address a long way down the stack 1.337 +TEST_F(GetCallerFrame, TraditionalScanLongWay) { 1.338 + stack_section.start() = 0x80000000; 1.339 + Label frame1_ebp; 1.340 + stack_section 1.341 + // frame 0 1.342 + .D32(0xf065dc76) // locals area: 1.343 + .D32(0x46ee2167) // garbage that doesn't look like 1.344 + .D32(0xbab023ec) // a return address 1.345 + .Append(20 * 4, 0) // a bunch of space 1.346 + .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) 1.347 + .D32(0x4000129d) // return address 1.348 + // frame 1 1.349 + .Append(8, 0) // space 1.350 + .Mark(&frame1_ebp) // %ebp points here 1.351 + .D32(0) // saved %ebp (stack end) 1.352 + .D32(0); // return address (stack end) 1.353 + 1.354 + RegionFromSection(); 1.355 + raw_context.eip = 0x4000f49d; 1.356 + raw_context.esp = stack_section.start().Value(); 1.357 + // Make the frame pointer bogus, to make the stackwalker scan the stack 1.358 + // for something that looks like a return address. 1.359 + raw_context.ebp = 0xd43eed6e; 1.360 + 1.361 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.362 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.363 + &frame_symbolizer); 1.364 + vector<const CodeModule*> modules_without_symbols; 1.365 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.366 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.367 + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); 1.368 + frames = call_stack.frames(); 1.369 + ASSERT_EQ(2U, frames->size()); 1.370 + 1.371 + { // To avoid reusing locals by mistake 1.372 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.373 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.374 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.375 + EXPECT_EQ(0x4000f49dU, frame0->instruction); 1.376 + EXPECT_EQ(0x4000f49dU, frame0->context.eip); 1.377 + EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 1.378 + EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); 1.379 + EXPECT_EQ(NULL, frame0->windows_frame_info); 1.380 + } 1.381 + 1.382 + { // To avoid reusing locals by mistake 1.383 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.384 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 1.385 + // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 1.386 + // walker does not actually fetch the EBP after a scan (forcing the 1.387 + // next frame to be scanned as well). But let's grandfather the existing 1.388 + // behavior in for now. 1.389 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.390 + | StackFrameX86::CONTEXT_VALID_ESP 1.391 + | StackFrameX86::CONTEXT_VALID_EBP), 1.392 + frame1->context_validity); 1.393 + EXPECT_EQ(0x4000129dU, frame1->instruction + 1); 1.394 + EXPECT_EQ(0x4000129dU, frame1->context.eip); 1.395 + EXPECT_EQ(0x80000064U, frame1->context.esp); 1.396 + EXPECT_EQ(0xd43eed6eU, frame1->context.ebp); 1.397 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.398 + } 1.399 +} 1.400 + 1.401 +// Use Windows frame data (a "STACK WIN 4" record, from a 1.402 +// FrameTypeFrameData DIA record) to walk a stack frame. 1.403 +TEST_F(GetCallerFrame, WindowsFrameData) { 1.404 + SetModuleSymbols(&module1, 1.405 + "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" 1.406 + " $T2 $esp .cbSavedRegs + =" 1.407 + " $T0 .raSearchStart =" 1.408 + " $eip $T0 ^ =" 1.409 + " $esp $T0 4 + =" 1.410 + " $ebx $T2 4 - ^ =" 1.411 + " $edi $T2 8 - ^ =" 1.412 + " $esi $T2 12 - ^ =" 1.413 + " $ebp $T2 16 - ^ =\n"); 1.414 + Label frame1_esp, frame1_ebp; 1.415 + stack_section.start() = 0x80000000; 1.416 + stack_section 1.417 + // frame 0 1.418 + .D32(frame1_ebp) // saved regs: %ebp 1.419 + .D32(0xa7120d1a) // %esi 1.420 + .D32(0x630891be) // %edi 1.421 + .D32(0x9068a878) // %ebx 1.422 + .D32(0xa08ea45f) // locals: unused 1.423 + .D32(0x40001350) // return address 1.424 + // frame 1 1.425 + .Mark(&frame1_esp) 1.426 + .Append(12, 0) // empty space 1.427 + .Mark(&frame1_ebp) 1.428 + .D32(0) // saved %ebp (stack end) 1.429 + .D32(0); // saved %eip (stack end) 1.430 + 1.431 + RegionFromSection(); 1.432 + raw_context.eip = 0x4000aa85; 1.433 + raw_context.esp = stack_section.start().Value(); 1.434 + raw_context.ebp = 0xf052c1de; // should not be needed to walk frame 1.435 + 1.436 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.437 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.438 + &frame_symbolizer); 1.439 + vector<const CodeModule*> modules_without_symbols; 1.440 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.441 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.442 + frames = call_stack.frames(); 1.443 + ASSERT_EQ(2U, frames->size()); 1.444 + 1.445 + { // To avoid reusing locals by mistake 1.446 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.447 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.448 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.449 + EXPECT_EQ(0x4000aa85U, frame0->instruction); 1.450 + EXPECT_EQ(0x4000aa85U, frame0->context.eip); 1.451 + EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 1.452 + EXPECT_EQ(0xf052c1deU, frame0->context.ebp); 1.453 + EXPECT_TRUE(frame0->windows_frame_info != NULL); 1.454 + } 1.455 + 1.456 + { // To avoid reusing locals by mistake 1.457 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.458 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.459 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.460 + | StackFrameX86::CONTEXT_VALID_ESP 1.461 + | StackFrameX86::CONTEXT_VALID_EBP 1.462 + | StackFrameX86::CONTEXT_VALID_EBX 1.463 + | StackFrameX86::CONTEXT_VALID_ESI 1.464 + | StackFrameX86::CONTEXT_VALID_EDI), 1.465 + frame1->context_validity); 1.466 + EXPECT_EQ(0x40001350U, frame1->instruction + 1); 1.467 + EXPECT_EQ(0x40001350U, frame1->context.eip); 1.468 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.469 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.470 + EXPECT_EQ(0x9068a878U, frame1->context.ebx); 1.471 + EXPECT_EQ(0xa7120d1aU, frame1->context.esi); 1.472 + EXPECT_EQ(0x630891beU, frame1->context.edi); 1.473 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.474 + } 1.475 +} 1.476 + 1.477 +// Use Windows frame data (a "STACK WIN 4" record, from a 1.478 +// FrameTypeFrameData DIA record) to walk a stack frame where the stack 1.479 +// is aligned and we must search 1.480 +TEST_F(GetCallerFrame, WindowsFrameDataAligned) { 1.481 + SetModuleSymbols(&module1, 1.482 + "STACK WIN 4 aa85 176 0 0 4 4 8 0 1" 1.483 + " $T1 .raSearch =" 1.484 + " $T0 $T1 4 - 8 @ =" 1.485 + " $ebp $T1 4 - ^ =" 1.486 + " $eip $T1 ^ =" 1.487 + " $esp $T1 4 + ="); 1.488 + Label frame1_esp, frame1_ebp; 1.489 + stack_section.start() = 0x80000000; 1.490 + stack_section 1.491 + // frame 0 1.492 + .D32(0x0ffa0ffa) // unused saved register 1.493 + .D32(0xdeaddead) // locals 1.494 + .D32(0xbeefbeef) 1.495 + .D32(0) // 8-byte alignment 1.496 + .D32(frame1_ebp) 1.497 + .D32(0x5000129d) // return address 1.498 + // frame 1 1.499 + .Mark(&frame1_esp) 1.500 + .D32(0x1) // parameter 1.501 + .Mark(&frame1_ebp) 1.502 + .D32(0) // saved %ebp (stack end) 1.503 + .D32(0); // saved %eip (stack end) 1.504 + 1.505 + RegionFromSection(); 1.506 + raw_context.eip = 0x4000aa85; 1.507 + raw_context.esp = stack_section.start().Value(); 1.508 + raw_context.ebp = 0xf052c1de; // should not be needed to walk frame 1.509 + 1.510 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.511 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.512 + &frame_symbolizer); 1.513 + vector<const CodeModule*> modules_without_symbols; 1.514 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.515 + ASSERT_EQ(1U, modules_without_symbols.size()); 1.516 + ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); 1.517 + frames = call_stack.frames(); 1.518 + ASSERT_EQ(2U, frames->size()); 1.519 + 1.520 + { // To avoid reusing locals by mistake 1.521 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.522 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.523 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.524 + EXPECT_EQ(0x4000aa85U, frame0->instruction); 1.525 + EXPECT_EQ(0x4000aa85U, frame0->context.eip); 1.526 + EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 1.527 + EXPECT_EQ(0xf052c1deU, frame0->context.ebp); 1.528 + EXPECT_TRUE(frame0->windows_frame_info != NULL); 1.529 + } 1.530 + 1.531 + { // To avoid reusing locals by mistake 1.532 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.533 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.534 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.535 + | StackFrameX86::CONTEXT_VALID_ESP 1.536 + | StackFrameX86::CONTEXT_VALID_EBP), 1.537 + frame1->context_validity); 1.538 + EXPECT_EQ(0x5000129dU, frame1->instruction + 1); 1.539 + EXPECT_EQ(0x5000129dU, frame1->context.eip); 1.540 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.541 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.542 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.543 + } 1.544 +} 1.545 + 1.546 +// Use Windows frame data (a "STACK WIN 4" record, from a 1.547 +// FrameTypeFrameData DIA record) to walk a frame, and depend on the 1.548 +// parameter size from the callee as well. 1.549 +TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { 1.550 + SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n"); 1.551 + SetModuleSymbols(&module2, 1.552 + // Note bogus parameter size in FUNC record; the stack walker 1.553 + // should prefer the STACK WIN record, and see '4' below. 1.554 + "FUNC aa85 176 beef module2::whine\n" 1.555 + "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" 1.556 + " $T2 $esp .cbLocals + .cbSavedRegs + =" 1.557 + " $T0 .raSearchStart =" 1.558 + " $eip $T0 ^ =" 1.559 + " $esp $T0 4 + =" 1.560 + " $ebp $T0 20 - ^ =" 1.561 + " $ebx $T0 8 - ^ =\n"); 1.562 + Label frame0_esp, frame0_ebp; 1.563 + Label frame1_esp; 1.564 + Label frame2_esp, frame2_ebp; 1.565 + stack_section.start() = 0x80000000; 1.566 + stack_section 1.567 + // frame 0, in module1::wheedle. Traditional frame. 1.568 + .Mark(&frame0_esp) 1.569 + .Append(16, 0) // frame space 1.570 + .Mark(&frame0_ebp) 1.571 + .D32(0x6fa902e0) // saved %ebp. Not a frame pointer. 1.572 + .D32(0x5000aa95) // return address, in module2::whine 1.573 + // frame 1, in module2::whine. FrameData frame. 1.574 + .Mark(&frame1_esp) 1.575 + .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle 1.576 + .D32(0xbdc92f9f) // argument 2 1.577 + .D32(0x0b1d8442) // argument 1 1.578 + .D32(frame2_ebp) // saved %ebp 1.579 + .D32(0xb1b90a15) // unused 1.580 + .D32(0xf18e072d) // unused 1.581 + .D32(0x2558c7f3) // saved %ebx 1.582 + .D32(0x0365e25e) // unused 1.583 + .D32(0x2a179e38) // return address; $T0 points here 1.584 + // frame 2, in no module 1.585 + .Mark(&frame2_esp) 1.586 + .Append(12, 0) // empty space 1.587 + .Mark(&frame2_ebp) 1.588 + .D32(0) // saved %ebp (stack end) 1.589 + .D32(0); // saved %eip (stack end) 1.590 + 1.591 + RegionFromSection(); 1.592 + raw_context.eip = 0x40001004; // in module1::wheedle 1.593 + raw_context.esp = stack_section.start().Value(); 1.594 + raw_context.ebp = frame0_ebp.Value(); 1.595 + 1.596 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.597 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.598 + &frame_symbolizer); 1.599 + vector<const CodeModule*> modules_without_symbols; 1.600 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.601 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.602 + frames = call_stack.frames(); 1.603 + ASSERT_EQ(3U, frames->size()); 1.604 + 1.605 + { // To avoid reusing locals by mistake 1.606 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.607 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.608 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.609 + EXPECT_EQ(0x40001004U, frame0->instruction); 1.610 + EXPECT_EQ(0x40001004U, frame0->context.eip); 1.611 + EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1.612 + EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 1.613 + EXPECT_EQ(&module1, frame0->module); 1.614 + EXPECT_EQ("module1::wheedle", frame0->function_name); 1.615 + EXPECT_EQ(0x40001000U, frame0->function_base); 1.616 + // The FUNC record for module1::wheedle should have produced a 1.617 + // WindowsFrameInfo structure with only the parameter size valid. 1.618 + ASSERT_TRUE(frame0->windows_frame_info != NULL); 1.619 + EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, 1.620 + frame0->windows_frame_info->valid); 1.621 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN, 1.622 + frame0->windows_frame_info->type_); 1.623 + EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size); 1.624 + } 1.625 + 1.626 + { // To avoid reusing locals by mistake 1.627 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.628 + EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 1.629 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.630 + | StackFrameX86::CONTEXT_VALID_ESP 1.631 + | StackFrameX86::CONTEXT_VALID_EBP), 1.632 + frame1->context_validity); 1.633 + EXPECT_EQ(0x5000aa95U, frame1->instruction + 1); 1.634 + EXPECT_EQ(0x5000aa95U, frame1->context.eip); 1.635 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.636 + EXPECT_EQ(0x6fa902e0U, frame1->context.ebp); 1.637 + EXPECT_EQ(&module2, frame1->module); 1.638 + EXPECT_EQ("module2::whine", frame1->function_name); 1.639 + EXPECT_EQ(0x5000aa85U, frame1->function_base); 1.640 + ASSERT_TRUE(frame1->windows_frame_info != NULL); 1.641 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 1.642 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1.643 + frame1->windows_frame_info->type_); 1.644 + // This should not see the 0xbeef parameter size from the FUNC 1.645 + // record, but should instead see the STACK WIN record. 1.646 + EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size); 1.647 + } 1.648 + 1.649 + { // To avoid reusing locals by mistake 1.650 + StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); 1.651 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 1.652 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.653 + | StackFrameX86::CONTEXT_VALID_ESP 1.654 + | StackFrameX86::CONTEXT_VALID_EBP 1.655 + | StackFrameX86::CONTEXT_VALID_EBX), 1.656 + frame2->context_validity); 1.657 + EXPECT_EQ(0x2a179e38U, frame2->instruction + 1); 1.658 + EXPECT_EQ(0x2a179e38U, frame2->context.eip); 1.659 + EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); 1.660 + EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp); 1.661 + EXPECT_EQ(0x2558c7f3U, frame2->context.ebx); 1.662 + EXPECT_EQ(NULL, frame2->module); 1.663 + EXPECT_EQ(NULL, frame2->windows_frame_info); 1.664 + } 1.665 +} 1.666 + 1.667 +// Use Windows frame data (a "STACK WIN 4" record, from a 1.668 +// FrameTypeFrameData DIA record) to walk a stack frame, where the 1.669 +// expression fails to yield both an $eip and an $ebp value, and the stack 1.670 +// walker must scan. 1.671 +TEST_F(GetCallerFrame, WindowsFrameDataScan) { 1.672 + SetModuleSymbols(&module1, 1.673 + "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n"); 1.674 + // Mark frame 1's PC as the end of the stack. 1.675 + SetModuleSymbols(&module2, 1.676 + "FUNC 7c38 accf 0 module2::function\n" 1.677 + "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n"); 1.678 + Label frame1_esp; 1.679 + stack_section.start() = 0x80000000; 1.680 + stack_section 1.681 + // frame 0 1.682 + .Append(16, 0x2a) // unused, garbage 1.683 + .D32(0x50007ce9) // return address 1.684 + // frame 1 1.685 + .Mark(&frame1_esp) 1.686 + .Append(8, 0); // empty space 1.687 + 1.688 + RegionFromSection(); 1.689 + raw_context.eip = 0x40000c9c; 1.690 + raw_context.esp = stack_section.start().Value(); 1.691 + raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame 1.692 + 1.693 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.694 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.695 + &frame_symbolizer); 1.696 + vector<const CodeModule*> modules_without_symbols; 1.697 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.698 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.699 + frames = call_stack.frames(); 1.700 + ASSERT_EQ(2U, frames->size()); 1.701 + 1.702 + { // To avoid reusing locals by mistake 1.703 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.704 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.705 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.706 + EXPECT_EQ(0x40000c9cU, frame0->instruction); 1.707 + EXPECT_EQ(0x40000c9cU, frame0->context.eip); 1.708 + EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 1.709 + EXPECT_EQ(0x2ae314cdU, frame0->context.ebp); 1.710 + EXPECT_TRUE(frame0->windows_frame_info != NULL); 1.711 + } 1.712 + 1.713 + { // To avoid reusing locals by mistake 1.714 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.715 + EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 1.716 + // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker 1.717 + // does not actually fetch the EBP after a scan (forcing the next frame 1.718 + // to be scanned as well). But let's grandfather the existing behavior in 1.719 + // for now. 1.720 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.721 + | StackFrameX86::CONTEXT_VALID_ESP 1.722 + | StackFrameX86::CONTEXT_VALID_EBP), 1.723 + frame1->context_validity); 1.724 + EXPECT_EQ(0x50007ce9U, frame1->instruction + 1); 1.725 + EXPECT_EQ(0x50007ce9U, frame1->context.eip); 1.726 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.727 + EXPECT_TRUE(frame1->windows_frame_info != NULL); 1.728 + } 1.729 +} 1.730 + 1.731 +// Use Windows frame data (a "STACK WIN 4" record, from a 1.732 +// FrameTypeFrameData DIA record) to walk a stack frame, where the 1.733 +// expression yields an $eip that falls outside of any module, and the 1.734 +// stack walker must scan. 1.735 +TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { 1.736 + SetModuleSymbols(&module1, 1.737 + "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1" 1.738 + // A traditional frame, actually. 1.739 + " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n"); 1.740 + // Mark frame 1's PC as the end of the stack. 1.741 + SetModuleSymbols(&module2, 1.742 + "FUNC cfdb 8406 0 module2::function\n" 1.743 + "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n"); 1.744 + stack_section.start() = 0x80000000; 1.745 + 1.746 + // In this stack, the context's %ebp is pointing at the wrong place, so 1.747 + // the stack walker needs to scan to find the return address, and then 1.748 + // scan again to find the caller's saved %ebp. 1.749 + Label frame0_ebp, frame1_ebp, frame1_esp; 1.750 + stack_section 1.751 + // frame 0 1.752 + .Append(8, 0x2a) // garbage 1.753 + .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point 1.754 + // at *** below 1.755 + // The STACK WIN record says that the following two values are 1.756 + // frame 1's saved %ebp and return address, but the %ebp is wrong; 1.757 + // they're garbage. The stack walker will scan for the right values. 1.758 + .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp 1.759 + .D32(0x17847f5b) // alleged to be frame 1's return address 1.760 + .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find 1.761 + .D32(0x2b2b2b2b) // first word of realigned register save area 1.762 + // *** frame 0 %ebp ought to be pointing here 1.763 + .D32(0x2c2c2c2c) // realigned locals area 1.764 + .D32(0x5000d000) // frame 1's real saved %eip; scan will find 1.765 + // Frame 1, in module2::function. The STACK WIN record describes 1.766 + // this as the oldest frame, without referring to its contents, so 1.767 + // we needn't to provide any actual data here. 1.768 + .Mark(&frame1_esp) 1.769 + .Mark(&frame1_ebp) // frame 1 %ebp points here 1.770 + // A dummy value for frame 1's %ebp to point at. The scan recognizes the 1.771 + // saved %ebp because it points to a valid word in the stack memory region. 1.772 + .D32(0x2d2d2d2d); 1.773 + 1.774 + RegionFromSection(); 1.775 + raw_context.eip = 0x40000700; 1.776 + raw_context.esp = stack_section.start().Value(); 1.777 + raw_context.ebp = frame0_ebp.Value(); 1.778 + 1.779 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.780 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.781 + &frame_symbolizer); 1.782 + vector<const CodeModule*> modules_without_symbols; 1.783 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.784 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.785 + frames = call_stack.frames(); 1.786 + ASSERT_EQ(2U, frames->size()); 1.787 + 1.788 + { // To avoid reusing locals by mistake 1.789 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.790 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.791 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.792 + EXPECT_EQ(0x40000700U, frame0->instruction); 1.793 + EXPECT_EQ(0x40000700U, frame0->context.eip); 1.794 + EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 1.795 + EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 1.796 + EXPECT_TRUE(frame0->windows_frame_info != NULL); 1.797 + } 1.798 + 1.799 + { // To avoid reusing locals by mistake 1.800 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.801 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); 1.802 + // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 1.803 + // walker does not actually fetch the EBP after a scan (forcing the 1.804 + // next frame to be scanned as well). But let's grandfather the existing 1.805 + // behavior in for now. 1.806 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.807 + | StackFrameX86::CONTEXT_VALID_ESP 1.808 + | StackFrameX86::CONTEXT_VALID_EBP), 1.809 + frame1->context_validity); 1.810 + EXPECT_EQ(0x5000d000U, frame1->instruction + 1); 1.811 + EXPECT_EQ(0x5000d000U, frame1->context.eip); 1.812 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.813 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.814 + EXPECT_TRUE(frame1->windows_frame_info != NULL); 1.815 + } 1.816 +} 1.817 + 1.818 +// Use Windows FrameTypeFPO data to walk a stack frame for a function that 1.819 +// does not modify %ebp from the value it had in the caller. 1.820 +TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { 1.821 + SetModuleSymbols(&module1, 1.822 + // Note bogus parameter size in FUNC record; the walker 1.823 + // should prefer the STACK WIN record, and see the '8' below. 1.824 + "FUNC e8a8 100 feeb module1::discombobulated\n" 1.825 + "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n"); 1.826 + Label frame0_esp; 1.827 + Label frame1_esp, frame1_ebp; 1.828 + stack_section.start() = 0x80000000; 1.829 + stack_section 1.830 + // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. 1.831 + .Mark(&frame0_esp) 1.832 + // no outgoing parameters; this is the youngest frame. 1.833 + .D32(0x7c521352) // four bytes of saved registers 1.834 + .Append(0x10, 0x42) // local area 1.835 + .D32(0x40009b5b) // return address, in module1, no function 1.836 + // frame 1, in module1, no function. 1.837 + .Mark(&frame1_esp) 1.838 + .D32(0xf60ea7fc) // junk 1.839 + .Mark(&frame1_ebp) 1.840 + .D32(0) // saved %ebp (stack end) 1.841 + .D32(0); // saved %eip (stack end) 1.842 + 1.843 + RegionFromSection(); 1.844 + raw_context.eip = 0x4000e8b8; // in module1::whine 1.845 + raw_context.esp = stack_section.start().Value(); 1.846 + // Frame pointer unchanged from caller. 1.847 + raw_context.ebp = frame1_ebp.Value(); 1.848 + 1.849 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.850 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.851 + &frame_symbolizer); 1.852 + vector<const CodeModule*> modules_without_symbols; 1.853 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.854 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.855 + frames = call_stack.frames(); 1.856 + ASSERT_EQ(2U, frames->size()); 1.857 + 1.858 + { // To avoid reusing locals by mistake 1.859 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.860 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.861 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.862 + EXPECT_EQ(0x4000e8b8U, frame0->instruction); 1.863 + EXPECT_EQ(0x4000e8b8U, frame0->context.eip); 1.864 + EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1.865 + EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); // unchanged from caller 1.866 + EXPECT_EQ(&module1, frame0->module); 1.867 + EXPECT_EQ("module1::discombobulated", frame0->function_name); 1.868 + EXPECT_EQ(0x4000e8a8U, frame0->function_base); 1.869 + // The STACK WIN record for module1::discombobulated should have 1.870 + // produced a fully populated WindowsFrameInfo structure. 1.871 + ASSERT_TRUE(frame0->windows_frame_info != NULL); 1.872 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 1.873 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 1.874 + frame0->windows_frame_info->type_); 1.875 + EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size); 1.876 + } 1.877 + 1.878 + { // To avoid reusing locals by mistake 1.879 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.880 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.881 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.882 + | StackFrameX86::CONTEXT_VALID_ESP 1.883 + | StackFrameX86::CONTEXT_VALID_EBP), 1.884 + frame1->context_validity); 1.885 + EXPECT_EQ(0x40009b5bU, frame1->instruction + 1); 1.886 + EXPECT_EQ(0x40009b5bU, frame1->context.eip); 1.887 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.888 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.889 + EXPECT_EQ(&module1, frame1->module); 1.890 + EXPECT_EQ("", frame1->function_name); 1.891 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.892 + } 1.893 +} 1.894 + 1.895 +// Use Windows FrameTypeFPO data to walk a stack frame for a function 1.896 +// that uses %ebp for its own purposes, saving the value it had in the 1.897 +// caller in the standard place in the saved register area. 1.898 +TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { 1.899 + SetModuleSymbols(&module1, 1.900 + // Note bogus parameter size in FUNC record; the walker 1.901 + // should prefer the STACK WIN record, and see the '8' below. 1.902 + "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n" 1.903 + "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n"); 1.904 + Label frame0_esp; 1.905 + Label frame1_esp, frame1_ebp; 1.906 + stack_section.start() = 0x80000000; 1.907 + stack_section 1.908 + // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. 1.909 + .Mark(&frame0_esp) 1.910 + // no outgoing parameters; this is the youngest frame. 1.911 + .D32(frame1_ebp) // saved register area: saved %ebp 1.912 + .D32(0xb68bd5f9) // saved register area: something else 1.913 + .D32(0xd25d05fc) // local area 1.914 + .D32(0x4000debe) // return address, in module1, no function 1.915 + // frame 1, in module1, no function. 1.916 + .Mark(&frame1_esp) 1.917 + .D32(0xf0c9a974) // junk 1.918 + .Mark(&frame1_ebp) 1.919 + .D32(0) // saved %ebp (stack end) 1.920 + .D32(0); // saved %eip (stack end) 1.921 + 1.922 + RegionFromSection(); 1.923 + raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens 1.924 + raw_context.esp = stack_section.start().Value(); 1.925 + // RaisedByTheAliens uses %ebp for its own mysterious purposes. 1.926 + raw_context.ebp = 0xecbdd1a5; 1.927 + 1.928 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.929 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.930 + &frame_symbolizer); 1.931 + vector<const CodeModule*> modules_without_symbols; 1.932 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.933 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.934 + frames = call_stack.frames(); 1.935 + ASSERT_EQ(2U, frames->size()); 1.936 + 1.937 + { // To avoid reusing locals by mistake 1.938 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.939 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.940 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.941 + EXPECT_EQ(0x40009ab8U, frame0->instruction); 1.942 + EXPECT_EQ(0x40009ab8U, frame0->context.eip); 1.943 + EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1.944 + EXPECT_EQ(0xecbdd1a5, frame0->context.ebp); 1.945 + EXPECT_EQ(&module1, frame0->module); 1.946 + EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name); 1.947 + EXPECT_EQ(0x40009aa8U, frame0->function_base); 1.948 + // The STACK WIN record for module1::RaisedByTheAliens should have 1.949 + // produced a fully populated WindowsFrameInfo structure. 1.950 + ASSERT_TRUE(frame0->windows_frame_info != NULL); 1.951 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 1.952 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 1.953 + frame0->windows_frame_info->type_); 1.954 + EXPECT_EQ("", frame0->windows_frame_info->program_string); 1.955 + EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer); 1.956 + } 1.957 + 1.958 + { // To avoid reusing locals by mistake 1.959 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.960 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.961 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.962 + | StackFrameX86::CONTEXT_VALID_ESP 1.963 + | StackFrameX86::CONTEXT_VALID_EBP), 1.964 + frame1->context_validity); 1.965 + EXPECT_EQ(0x4000debeU, frame1->instruction + 1); 1.966 + EXPECT_EQ(0x4000debeU, frame1->context.eip); 1.967 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.968 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.969 + EXPECT_EQ(&module1, frame1->module); 1.970 + EXPECT_EQ("", frame1->function_name); 1.971 + EXPECT_EQ(NULL, frame1->windows_frame_info); 1.972 + } 1.973 +} 1.974 + 1.975 +// This is a regression unit test which covers a bug which has to do with 1.976 +// FPO-optimized Windows system call stubs in the context frame. There is 1.977 +// a more recent Windows system call dispatch mechanism which differs from 1.978 +// the one which is being tested here. The newer system call dispatch 1.979 +// mechanism creates an extra context frame (KiFastSystemCallRet). 1.980 +TEST_F(GetCallerFrame, WindowsFPOSystemCall) { 1.981 + SetModuleSymbols(&module3, // ntdll.dll 1.982 + "PUBLIC 1f8ac c ZwWaitForSingleObject\n" 1.983 + "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n"); 1.984 + SetModuleSymbols(&module4, // kernelbase.dll 1.985 + "PUBLIC 109f9 c WaitForSingleObjectEx\n" 1.986 + "PUBLIC 36590 0 _except_handler4\n" 1.987 + "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip " 1.988 + "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 1.989 + "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" 1.990 + "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip " 1.991 + "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 " 1.992 + ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); 1.993 + SetModuleSymbols(&module5, // kernel32.dll 1.994 + "PUBLIC 11136 8 WaitForSingleObject\n" 1.995 + "PUBLIC 11151 c WaitForSingleObjectExImplementation\n" 1.996 + "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip " 1.997 + "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 1.998 + "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" 1.999 + "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip " 1.1000 + "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 1.1001 + "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); 1.1002 + SetModuleSymbols(&module6, // chrome.dll 1.1003 + "FILE 7038 some_file_name.h\n" 1.1004 + "FILE 839776 some_file_name.cc\n" 1.1005 + "FUNC 217fda 17 4 function_217fda\n" 1.1006 + "217fda 4 102 839776\n" 1.1007 + "FUNC 217ff1 a 4 function_217ff1\n" 1.1008 + "217ff1 0 594 7038\n" 1.1009 + "217ff1 a 596 7038\n" 1.1010 + "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n"); 1.1011 + 1.1012 + Label frame0_esp, frame1_esp; 1.1013 + Label frame1_ebp, frame2_ebp, frame3_ebp; 1.1014 + stack_section.start() = 0x002ff290; 1.1015 + stack_section 1.1016 + .Mark(&frame0_esp) 1.1017 + .D32(0x771ef8c1) // EIP in frame 0 (system call) 1.1018 + .D32(0x75fa0a91) // return address of frame 0 1.1019 + .Mark(&frame1_esp) 1.1020 + .D32(0x000017b0) // args to child 1.1021 + .D32(0x00000000) 1.1022 + .D32(0x002ff2d8) 1.1023 + .D32(0x88014a2e) 1.1024 + .D32(0x002ff364) 1.1025 + .D32(0x000017b0) 1.1026 + .D32(0x00000000) 1.1027 + .D32(0x00000024) 1.1028 + .D32(0x00000001) 1.1029 + .D32(0x00000000) 1.1030 + .D32(0x00000000) 1.1031 + .D32(0x00000000) 1.1032 + .D32(0x00000000) 1.1033 + .D32(0x00000000) 1.1034 + .D32(0x00000000) 1.1035 + .D32(0x00000000) 1.1036 + .D32(0x9e3b9800) 1.1037 + .D32(0xfffffff7) 1.1038 + .D32(0x00000000) 1.1039 + .D32(0x002ff2a4) 1.1040 + .D32(0x64a07ff1) // random value to be confused with a return address 1.1041 + .D32(0x002ff8dc) 1.1042 + .D32(0x75fc6590) // random value to be confused with a return address 1.1043 + .D32(0xfdd2c6ea) 1.1044 + .D32(0x00000000) 1.1045 + .Mark(&frame1_ebp) 1.1046 + .D32(frame2_ebp) // Child EBP 1.1047 + .D32(0x75741194) // return address of frame 1 1.1048 + .D32(0x000017b0) // args to child 1.1049 + .D32(0x0036ee80) 1.1050 + .D32(0x00000000) 1.1051 + .D32(0x65bc7d14) 1.1052 + .Mark(&frame2_ebp) 1.1053 + .D32(frame3_ebp) // Child EBP 1.1054 + .D32(0x75741148) // return address of frame 2 1.1055 + .D32(0x000017b0) // args to child 1.1056 + .D32(0x0036ee80) 1.1057 + .D32(0x00000000) 1.1058 + .Mark(&frame3_ebp) 1.1059 + .D32(0) // saved %ebp (stack end) 1.1060 + .D32(0); // saved %eip (stack end) 1.1061 + 1.1062 + RegionFromSection(); 1.1063 + raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject 1.1064 + raw_context.esp = stack_section.start().Value(); 1.1065 + ASSERT_TRUE(raw_context.esp == frame0_esp.Value()); 1.1066 + raw_context.ebp = frame1_ebp.Value(); 1.1067 + 1.1068 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.1069 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.1070 + &frame_symbolizer); 1.1071 + vector<const CodeModule*> modules_without_symbols; 1.1072 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.1073 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.1074 + frames = call_stack.frames(); 1.1075 + 1.1076 + ASSERT_EQ(4U, frames->size()); 1.1077 + 1.1078 + { // To avoid reusing locals by mistake 1.1079 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.1080 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.1081 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.1082 + EXPECT_EQ(0x771ef8c1U, frame0->instruction); 1.1083 + EXPECT_EQ(0x771ef8c1U, frame0->context.eip); 1.1084 + EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1.1085 + EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); 1.1086 + EXPECT_EQ(&module3, frame0->module); 1.1087 + EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name); 1.1088 + // The STACK WIN record for module3!ZwWaitForSingleObject should have 1.1089 + // produced a fully populated WindowsFrameInfo structure. 1.1090 + ASSERT_TRUE(frame0->windows_frame_info != NULL); 1.1091 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 1.1092 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 1.1093 + frame0->windows_frame_info->type_); 1.1094 + EXPECT_EQ("", frame0->windows_frame_info->program_string); 1.1095 + EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); 1.1096 + } 1.1097 + 1.1098 + { // To avoid reusing locals by mistake 1.1099 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.1100 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.1101 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1.1102 + | StackFrameX86::CONTEXT_VALID_ESP 1.1103 + | StackFrameX86::CONTEXT_VALID_EBP), 1.1104 + frame1->context_validity); 1.1105 + EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1); 1.1106 + EXPECT_EQ(0x75fa0a91U, frame1->context.eip); 1.1107 + EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1.1108 + EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1.1109 + EXPECT_EQ(&module4, frame1->module); 1.1110 + EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name); 1.1111 + // The STACK WIN record for module4!WaitForSingleObjectEx should have 1.1112 + // produced a fully populated WindowsFrameInfo structure. 1.1113 + ASSERT_TRUE(frame1->windows_frame_info != NULL); 1.1114 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 1.1115 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1.1116 + frame1->windows_frame_info->type_); 1.1117 + EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 1.1118 + "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", 1.1119 + frame1->windows_frame_info->program_string); 1.1120 + EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); 1.1121 + } 1.1122 +} 1.1123 + 1.1124 +// Scan the stack for a better return address and potentially skip frames 1.1125 +// when the calculated return address is not in a known module. 1.1126 +// Note, that the span of this scan is somewhat arbitrarily limited to 30 1.1127 +// search words (pointers): 1.1128 +// const int kRASearchWords = 30; 1.1129 +// This means that frames can be skipped only when their size is relatively 1.1130 +// small: smaller than kRASearchWords * sizeof(InstructionType) 1.1131 +TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { 1.1132 + MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1"); 1.1133 + SetModuleSymbols(&msvcrt_dll, // msvcrt.dll 1.1134 + "PUBLIC 38180 0 wcsstr\n" 1.1135 + "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 " 1.1136 + "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1.1137 + "- = $P $T0 4 + .cbParams + =\n"); 1.1138 + 1.1139 + MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1"); 1.1140 + SetModuleSymbols(&kernel32_dll, // kernel32.dll 1.1141 + "PUBLIC efda 8 FindNextFileW\n" 1.1142 + "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 " 1.1143 + "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1.1144 + "- = $P $T0 4 + .cbParams + =\n"); 1.1145 + 1.1146 + MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1"); 1.1147 + SetModuleSymbols(&chrome_dll, // chrome.dll 1.1148 + "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n" 1.1149 + "e3cff 1a 711 2505\n" 1.1150 + "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = " 1.1151 + "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " 1.1152 + "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " 1.1153 + "$T0 160 - ^ =\n"); 1.1154 + 1.1155 + // Create some modules with some stock debugging information. 1.1156 + MockCodeModules local_modules; 1.1157 + local_modules.Add(&msvcrt_dll); 1.1158 + local_modules.Add(&kernel32_dll); 1.1159 + local_modules.Add(&chrome_dll); 1.1160 + 1.1161 + Label frame0_esp; 1.1162 + Label frame0_ebp; 1.1163 + Label frame1_ebp; 1.1164 + Label frame2_ebp; 1.1165 + Label frame3_ebp; 1.1166 + 1.1167 + stack_section.start() = 0x0932f2d0; 1.1168 + stack_section 1.1169 + .Mark(&frame0_esp) 1.1170 + .D32(0x0764e000) 1.1171 + .D32(0x0764e068) 1.1172 + .Mark(&frame0_ebp) 1.1173 + .D32(frame1_ebp) // Child EBP 1.1174 + .D32(0x001767a0) // return address of frame 0 1.1175 + // Not in known module 1.1176 + .D32(0x0764e0c6) 1.1177 + .D32(0x001bb1b8) 1.1178 + .D32(0x0764e068) 1.1179 + .D32(0x00000003) 1.1180 + .D32(0x0764e068) 1.1181 + .D32(0x00000003) 1.1182 + .D32(0x07578828) 1.1183 + .D32(0x0764e000) 1.1184 + .D32(0x00000000) 1.1185 + .D32(0x001c0010) 1.1186 + .D32(0x0764e0c6) 1.1187 + .Mark(&frame1_ebp) 1.1188 + .D32(frame2_ebp) // Child EBP 1.1189 + .D32(0x7c80f10f) // return address of frame 1 1.1190 + // inside kernel32!FindNextFileW 1.1191 + .D32(0x000008f8) 1.1192 + .D32(0x00000000) 1.1193 + .D32(0x00000000) 1.1194 + .D32(0x00000000) 1.1195 + .D32(0x0932f34c) 1.1196 + .D32(0x0764e000) 1.1197 + .D32(0x00001000) 1.1198 + .D32(0x00000000) 1.1199 + .D32(0x00000001) 1.1200 + .D32(0x00000000) 1.1201 + .D32(0x00000000) 1.1202 + .D32(0x0932f6a8) 1.1203 + .D32(0x00000000) 1.1204 + .D32(0x0932f6d8) 1.1205 + .D32(0x00000000) 1.1206 + .D32(0x000000d6) 1.1207 + .D32(0x0764e000) 1.1208 + .D32(0x7ff9a000) 1.1209 + .D32(0x0932f3fc) 1.1210 + .D32(0x00000001) 1.1211 + .D32(0x00000001) 1.1212 + .D32(0x07578828) 1.1213 + .D32(0x0000002e) 1.1214 + .D32(0x0932f340) 1.1215 + .D32(0x0932eef4) 1.1216 + .D32(0x0932ffdc) 1.1217 + .D32(0x7c839ad8) 1.1218 + .D32(0x7c80f0d8) 1.1219 + .D32(0x00000000) 1.1220 + .Mark(&frame2_ebp) 1.1221 + .D32(frame3_ebp) // Child EBP 1.1222 + .D32(0x01d13f91) // return address of frame 2 1.1223 + // inside chrome_dll!file_util::FileEnumerator::Next 1.1224 + .D32(0x07578828) 1.1225 + .D32(0x0932f6ac) 1.1226 + .D32(0x0932f9c4) 1.1227 + .D32(0x0932f9b4) 1.1228 + .D32(0x00000000) 1.1229 + .D32(0x00000003) 1.1230 + .D32(0x0932f978) 1.1231 + .D32(0x01094330) 1.1232 + .D32(0x00000000) 1.1233 + .D32(0x00000001) 1.1234 + .D32(0x01094330) 1.1235 + .D32(0x00000000) 1.1236 + .D32(0x00000000) 1.1237 + .D32(0x07f30000) 1.1238 + .D32(0x01c3ba17) 1.1239 + .D32(0x08bab840) 1.1240 + .D32(0x07f31580) 1.1241 + .D32(0x00000000) 1.1242 + .D32(0x00000007) 1.1243 + .D32(0x0932f940) 1.1244 + .D32(0x0000002e) 1.1245 + .D32(0x0932f40c) 1.1246 + .D32(0x01d13b53) 1.1247 + .D32(0x0932f958) 1.1248 + .D32(0x00000001) 1.1249 + .D32(0x00000007) 1.1250 + .D32(0x0932f940) 1.1251 + .D32(0x0000002e) 1.1252 + .D32(0x00000000) 1.1253 + .D32(0x0932f6ac) 1.1254 + .D32(0x01e13ef0) 1.1255 + .D32(0x00000001) 1.1256 + .D32(0x00000007) 1.1257 + .D32(0x0932f958) 1.1258 + .D32(0x08bab840) 1.1259 + .D32(0x0932f9b4) 1.1260 + .D32(0x00000000) 1.1261 + .D32(0x0932f9b4) 1.1262 + .D32(0x000000a7) 1.1263 + .D32(0x000000a7) 1.1264 + .D32(0x0932f998) 1.1265 + .D32(0x579627a2) 1.1266 + .Mark(&frame3_ebp) 1.1267 + .D32(0) // saved %ebp (stack end) 1.1268 + .D32(0); // saved %eip (stack end) 1.1269 + 1.1270 + RegionFromSection(); 1.1271 + raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr 1.1272 + raw_context.esp = frame0_esp.Value(); 1.1273 + raw_context.ebp = frame0_ebp.Value(); 1.1274 + // sanity 1.1275 + ASSERT_TRUE(raw_context.esp == stack_section.start().Value()); 1.1276 + ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8); 1.1277 + 1.1278 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.1279 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, 1.1280 + &local_modules, &frame_symbolizer); 1.1281 + vector<const CodeModule*> modules_without_symbols; 1.1282 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.1283 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.1284 + frames = call_stack.frames(); 1.1285 + 1.1286 + ASSERT_EQ(3U, frames->size()); 1.1287 + 1.1288 + { // To avoid reusing locals by mistake 1.1289 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.1290 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.1291 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.1292 + EXPECT_EQ(0x77c181cdU, frame0->instruction); 1.1293 + EXPECT_EQ(0x77c181cdU, frame0->context.eip); 1.1294 + EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1.1295 + EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 1.1296 + EXPECT_EQ(&msvcrt_dll, frame0->module); 1.1297 + EXPECT_EQ("wcsstr", frame0->function_name); 1.1298 + ASSERT_TRUE(frame0->windows_frame_info != NULL); 1.1299 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 1.1300 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1.1301 + frame0->windows_frame_info->type_); 1.1302 + EXPECT_EQ("$T0 $ebp = $eip $T0 " 1.1303 + "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1.1304 + "- = $P $T0 4 + .cbParams + =", 1.1305 + frame0->windows_frame_info->program_string); 1.1306 + // It has program string, so allocates_base_pointer is not expected 1.1307 + EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); 1.1308 + } 1.1309 + 1.1310 + { // To avoid reusing locals by mistake 1.1311 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.1312 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); 1.1313 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 1.1314 + StackFrameX86::CONTEXT_VALID_ESP | 1.1315 + StackFrameX86::CONTEXT_VALID_EBP), 1.1316 + frame1->context_validity); 1.1317 + EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1); 1.1318 + EXPECT_EQ(0x7c80f10fU, frame1->context.eip); 1.1319 + // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp. 1.1320 + EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp); 1.1321 + EXPECT_EQ(&kernel32_dll, frame1->module); 1.1322 + EXPECT_EQ("FindNextFileW", frame1->function_name); 1.1323 + ASSERT_TRUE(frame1->windows_frame_info != NULL); 1.1324 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 1.1325 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1.1326 + frame1->windows_frame_info->type_); 1.1327 + EXPECT_EQ("$T0 $ebp = $eip $T0 " 1.1328 + "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1.1329 + "- = $P $T0 4 + .cbParams + =", 1.1330 + frame1->windows_frame_info->program_string); 1.1331 + EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); 1.1332 + } 1.1333 + 1.1334 + { // To avoid reusing locals by mistake 1.1335 + StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); 1.1336 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 1.1337 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 1.1338 + StackFrameX86::CONTEXT_VALID_ESP | 1.1339 + StackFrameX86::CONTEXT_VALID_EBP), 1.1340 + frame2->context_validity); 1.1341 + EXPECT_EQ(0x01d13f91U, frame2->instruction + 1); 1.1342 + EXPECT_EQ(0x01d13f91U, frame2->context.eip); 1.1343 + // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp. 1.1344 + EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp); 1.1345 + EXPECT_EQ(&chrome_dll, frame2->module); 1.1346 + EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name); 1.1347 + ASSERT_TRUE(frame2->windows_frame_info != NULL); 1.1348 + EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); 1.1349 + EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1.1350 + frame2->windows_frame_info->type_); 1.1351 + EXPECT_EQ("$T1 .raSearch = " 1.1352 + "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " 1.1353 + "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " 1.1354 + "$T0 160 - ^ =", 1.1355 + frame2->windows_frame_info->program_string); 1.1356 + EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer); 1.1357 + } 1.1358 +} 1.1359 + 1.1360 +struct CFIFixture: public StackwalkerX86Fixture { 1.1361 + CFIFixture() { 1.1362 + // Provide a bunch of STACK CFI records; individual tests walk to the 1.1363 + // caller from every point in this series, expecting to find the same 1.1364 + // set of register values. 1.1365 + SetModuleSymbols(&module1, 1.1366 + // The youngest frame's function. 1.1367 + "FUNC 4000 1000 10 enchiridion\n" 1.1368 + // Initially, just a return address. 1.1369 + "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n" 1.1370 + // Push %ebx. 1.1371 + "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n" 1.1372 + // Move %esi into %ebx. Weird, but permitted. 1.1373 + "STACK CFI 4002 $esi: $ebx\n" 1.1374 + // Allocate frame space, and save %edi. 1.1375 + "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n" 1.1376 + // Put the return address in %edi. 1.1377 + "STACK CFI 4005 .ra: $edi\n" 1.1378 + // Save %ebp, and use it as a frame pointer. 1.1379 + "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n" 1.1380 + 1.1381 + // The calling function. 1.1382 + "FUNC 5000 1000 10 epictetus\n" 1.1383 + // Mark it as end of stack. 1.1384 + "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n"); 1.1385 + 1.1386 + // Provide some distinctive values for the caller's registers. 1.1387 + expected.esp = 0x80000000; 1.1388 + expected.eip = 0x40005510; 1.1389 + expected.ebp = 0xc0d4aab9; 1.1390 + expected.ebx = 0x60f20ce6; 1.1391 + expected.esi = 0x53d1379d; 1.1392 + expected.edi = 0xafbae234; 1.1393 + 1.1394 + // By default, registers are unchanged. 1.1395 + raw_context = expected; 1.1396 + } 1.1397 + 1.1398 + // Walk the stack, using stack_section as the contents of the stack 1.1399 + // and raw_context as the current register values. (Set 1.1400 + // raw_context.esp to the stack's starting address.) Expect two 1.1401 + // stack frames; in the older frame, expect the callee-saves 1.1402 + // registers to have values matching those in 'expected'. 1.1403 + void CheckWalk() { 1.1404 + RegionFromSection(); 1.1405 + raw_context.esp = stack_section.start().Value(); 1.1406 + 1.1407 + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1.1408 + StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1.1409 + &frame_symbolizer); 1.1410 + vector<const CodeModule*> modules_without_symbols; 1.1411 + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); 1.1412 + ASSERT_EQ(0U, modules_without_symbols.size()); 1.1413 + frames = call_stack.frames(); 1.1414 + ASSERT_EQ(2U, frames->size()); 1.1415 + 1.1416 + { // To avoid reusing locals by mistake 1.1417 + StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1.1418 + EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1.1419 + ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1.1420 + EXPECT_EQ("enchiridion", frame0->function_name); 1.1421 + EXPECT_EQ(0x40004000U, frame0->function_base); 1.1422 + ASSERT_TRUE(frame0->windows_frame_info != NULL); 1.1423 + ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, 1.1424 + frame0->windows_frame_info->valid); 1.1425 + ASSERT_TRUE(frame0->cfi_frame_info != NULL); 1.1426 + } 1.1427 + 1.1428 + { // To avoid reusing locals by mistake 1.1429 + StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1.1430 + EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1.1431 + ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 1.1432 + StackFrameX86::CONTEXT_VALID_ESP | 1.1433 + StackFrameX86::CONTEXT_VALID_EBP | 1.1434 + StackFrameX86::CONTEXT_VALID_EBX | 1.1435 + StackFrameX86::CONTEXT_VALID_ESI | 1.1436 + StackFrameX86::CONTEXT_VALID_EDI), 1.1437 + frame1->context_validity); 1.1438 + EXPECT_EQ(expected.eip, frame1->context.eip); 1.1439 + EXPECT_EQ(expected.esp, frame1->context.esp); 1.1440 + EXPECT_EQ(expected.ebp, frame1->context.ebp); 1.1441 + EXPECT_EQ(expected.ebx, frame1->context.ebx); 1.1442 + EXPECT_EQ(expected.esi, frame1->context.esi); 1.1443 + EXPECT_EQ(expected.edi, frame1->context.edi); 1.1444 + EXPECT_EQ("epictetus", frame1->function_name); 1.1445 + } 1.1446 + } 1.1447 + 1.1448 + // The values the stack walker should find for the caller's registers. 1.1449 + MDRawContextX86 expected; 1.1450 +}; 1.1451 + 1.1452 +class CFI: public CFIFixture, public Test { }; 1.1453 + 1.1454 +TEST_F(CFI, At4000) { 1.1455 + Label frame1_esp = expected.esp; 1.1456 + stack_section 1.1457 + .D32(0x40005510) // return address 1.1458 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1459 + raw_context.eip = 0x40004000; 1.1460 + CheckWalk(); 1.1461 +} 1.1462 + 1.1463 +TEST_F(CFI, At4001) { 1.1464 + Label frame1_esp = expected.esp; 1.1465 + stack_section 1.1466 + .D32(0x60f20ce6) // saved %ebx 1.1467 + .D32(0x40005510) // return address 1.1468 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1469 + raw_context.eip = 0x40004001; 1.1470 + raw_context.ebx = 0x91aa9a8b; // callee's %ebx value 1.1471 + CheckWalk(); 1.1472 +} 1.1473 + 1.1474 +TEST_F(CFI, At4002) { 1.1475 + Label frame1_esp = expected.esp; 1.1476 + stack_section 1.1477 + .D32(0x60f20ce6) // saved %ebx 1.1478 + .D32(0x40005510) // return address 1.1479 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1480 + raw_context.eip = 0x40004002; 1.1481 + raw_context.ebx = 0x53d1379d; // saved %esi 1.1482 + raw_context.esi = 0xa5c790ed; // callee's %esi value 1.1483 + CheckWalk(); 1.1484 +} 1.1485 + 1.1486 +TEST_F(CFI, At4003) { 1.1487 + Label frame1_esp = expected.esp; 1.1488 + stack_section 1.1489 + .D32(0x56ec3db7) // garbage 1.1490 + .D32(0xafbae234) // saved %edi 1.1491 + .D32(0x53d67131) // garbage 1.1492 + .D32(0x60f20ce6) // saved %ebx 1.1493 + .D32(0x40005510) // return address 1.1494 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1495 + raw_context.eip = 0x40004003; 1.1496 + raw_context.ebx = 0x53d1379d; // saved %esi 1.1497 + raw_context.esi = 0xa97f229d; // callee's %esi 1.1498 + raw_context.edi = 0xb05cc997; // callee's %edi 1.1499 + CheckWalk(); 1.1500 +} 1.1501 + 1.1502 +// The results here should be the same as those at module offset 1.1503 +// 0x4003. 1.1504 +TEST_F(CFI, At4004) { 1.1505 + Label frame1_esp = expected.esp; 1.1506 + stack_section 1.1507 + .D32(0xe29782c2) // garbage 1.1508 + .D32(0xafbae234) // saved %edi 1.1509 + .D32(0x5ba29ce9) // garbage 1.1510 + .D32(0x60f20ce6) // saved %ebx 1.1511 + .D32(0x40005510) // return address 1.1512 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1513 + raw_context.eip = 0x40004004; 1.1514 + raw_context.ebx = 0x53d1379d; // saved %esi 1.1515 + raw_context.esi = 0x0fb7dc4e; // callee's %esi 1.1516 + raw_context.edi = 0x993b4280; // callee's %edi 1.1517 + CheckWalk(); 1.1518 +} 1.1519 + 1.1520 +TEST_F(CFI, At4005) { 1.1521 + Label frame1_esp = expected.esp; 1.1522 + stack_section 1.1523 + .D32(0xe29782c2) // garbage 1.1524 + .D32(0xafbae234) // saved %edi 1.1525 + .D32(0x5ba29ce9) // garbage 1.1526 + .D32(0x60f20ce6) // saved %ebx 1.1527 + .D32(0x8036cc02) // garbage 1.1528 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1529 + raw_context.eip = 0x40004005; 1.1530 + raw_context.ebx = 0x53d1379d; // saved %esi 1.1531 + raw_context.esi = 0x0fb7dc4e; // callee's %esi 1.1532 + raw_context.edi = 0x40005510; // return address 1.1533 + CheckWalk(); 1.1534 +} 1.1535 + 1.1536 +TEST_F(CFI, At4006) { 1.1537 + Label frame0_ebp; 1.1538 + Label frame1_esp = expected.esp; 1.1539 + stack_section 1.1540 + .D32(0xdcdd25cd) // garbage 1.1541 + .D32(0xafbae234) // saved %edi 1.1542 + .D32(0xc0d4aab9) // saved %ebp 1.1543 + .Mark(&frame0_ebp) // frame pointer points here 1.1544 + .D32(0x60f20ce6) // saved %ebx 1.1545 + .D32(0x8036cc02) // garbage 1.1546 + .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1.1547 + raw_context.eip = 0x40004006; 1.1548 + raw_context.ebp = frame0_ebp.Value(); 1.1549 + raw_context.ebx = 0x53d1379d; // saved %esi 1.1550 + raw_context.esi = 0x743833c9; // callee's %esi 1.1551 + raw_context.edi = 0x40005510; // return address 1.1552 + CheckWalk(); 1.1553 +} 1.1554 +