toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc

changeset 0
6474c204b198
     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 +

mercurial