1a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Copyright (c) 2010, Google Inc.
2a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// All rights reserved.
3a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy//
4a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Redistribution and use in source and binary forms, with or without
5a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// modification, are permitted provided that the following conditions are
6a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// met:
7a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy//
8a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy//     * Redistributions of source code must retain the above copyright
9a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// notice, this list of conditions and the following disclaimer.
10a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy//     * Redistributions in binary form must reproduce the above
11a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// copyright notice, this list of conditions and the following disclaimer
12a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// in the documentation and/or other materials provided with the
13a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// distribution.
14a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy//     * Neither the name of Google Inc. nor the names of its
15a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// contributors may be used to endorse or promote products derived from
16a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// this software without specific prior written permission.
17a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy//
18a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
30a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
32a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// stackwalker_x86_unittest.cc: Unit tests for StackwalkerX86 class.
33a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
34a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include <string>
35a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include <vector>
36a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
37a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "breakpad_googletest_includes.h"
38865df5af57922a4dc1e2a24e3f5c371d84f0f574jimblandy#include "common/test_assembler.h"
394e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h"
40a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/common/minidump_format.h"
41a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/processor/basic_source_line_resolver.h"
42a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/processor/call_stack.h"
435a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com#include "google_breakpad/processor/code_module.h"
44a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/processor/source_line_resolver_interface.h"
45a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/processor/stack_frame_cpu.h"
46a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "processor/stackwalker_unittest_utils.h"
47a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "processor/stackwalker_x86.h"
48a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "processor/windows_frame_info.h"
49a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
50a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::BasicSourceLineResolver;
51a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::CallStack;
525a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.comusing google_breakpad::CodeModule;
539753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.comusing google_breakpad::StackFrameSymbolizer;
54a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::StackFrame;
55a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::StackFrameX86;
5642b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.comusing google_breakpad::Stackwalker;
57a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::StackwalkerX86;
58a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::SystemInfo;
59a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::WindowsFrameInfo;
606f598cc435f8c557b33f85802f1571ef745c37b0ted.mielczarekusing google_breakpad::test_assembler::kLittleEndian;
616f598cc435f8c557b33f85802f1571ef745c37b0ted.mielczarekusing google_breakpad::test_assembler::Label;
626f598cc435f8c557b33f85802f1571ef745c37b0ted.mielczarekusing google_breakpad::test_assembler::Section;
63a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing std::vector;
64a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::_;
6584946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.comusing testing::AnyNumber;
66a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::Return;
67a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::SetArgumentPointee;
68a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::Test;
69a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
70a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyclass StackwalkerX86Fixture {
71a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy public:
72a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86Fixture()
73a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    : stack_section(kLittleEndian),
74a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy      // Give the two modules reasonable standard locations and names
75a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy      // for tests to play with.
76a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy      module1(0x40000000, 0x10000, "module1", "version1"),
772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      module2(0x50000000, 0x10000, "module2", "version2"),
782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      module3(0x771d0000, 0x180000, "module3", "version3"),
792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      module4(0x75f90000, 0x46000, "module4", "version4"),
802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      module5(0x75730000, 0x110000, "module5", "version5"),
812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      module6(0x647f0000, 0x1ba8000, "module6", "version6") {
82a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // Identify the system as a Linux system.
83a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    system_info.os = "Linux";
84a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    system_info.os_short = "linux";
85a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    system_info.os_version = "Salacious Skink";
86a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    system_info.cpu = "x86";
87a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    system_info.cpu_info = "";
88a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
89a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // Put distinctive values in the raw CPU context.
90a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    BrandContext(&raw_context);
91a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
92a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // Create some modules with some stock debugging information.
93a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    modules.Add(&module1);
94a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    modules.Add(&module2);
952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    modules.Add(&module3);
962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    modules.Add(&module4);
972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    modules.Add(&module5);
982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    modules.Add(&module6);
99a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
100a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // By default, none of the modules have symbol info; call
101a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // SetModuleSymbols to override this.
1022d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
103a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy      .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
10484946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com
10584946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com    // Avoid GMOCK WARNING "Uninteresting mock function call - returning
10684946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com    // directly" for FreeSymbolData().
10784946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com    EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
10842b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com
10942b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    // Reset max_frames_scanned since it's static.
11042b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    Stackwalker::set_max_frames_scanned(1024);
111a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  }
112a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
113a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Set the Breakpad symbol information that supplier should return for
114a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // MODULE to INFO.
115a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  void SetModuleSymbols(MockCodeModule *module, const string &info) {
1162d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    size_t buffer_size;
1172d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
1182d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
1195b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com      .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
1202d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                            SetArgumentPointee<4>(buffer_size),
121a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                            Return(MockSymbolSupplier::FOUND)));
122a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  }
123a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
124a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Populate stack_region with the contents of stack_section. Use
125a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // stack_section.start() as the region's starting address.
126a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  void RegionFromSection() {
127a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    string contents;
128a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    ASSERT_TRUE(stack_section.GetContents(&contents));
129a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    stack_region.Init(stack_section.start().Value(), contents);
130a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  }
131a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
132a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
133a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  void BrandContext(MDRawContextX86 *raw_context) {
1346162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint8_t x = 173;
135a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    for (size_t i = 0; i < sizeof(*raw_context); i++)
1366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com      reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
137a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  }
1387a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
139a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SystemInfo system_info;
140a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  MDRawContextX86 raw_context;
141a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Section stack_section;
142a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  MockMemoryRegion stack_region;
143a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  MockCodeModule module1;
144a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  MockCodeModule module2;
1452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  MockCodeModule module3;
1462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  MockCodeModule module4;
1472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  MockCodeModule module5;
1482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  MockCodeModule module6;
149a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  MockCodeModules modules;
150a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  MockSymbolSupplier supplier;
151a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  BasicSourceLineResolver resolver;
152a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  CallStack call_stack;
153a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  const vector<StackFrame *> *frames;
154a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy};
155a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
156281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarekclass SanityCheck: public StackwalkerX86Fixture, public Test { };
157281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek
158281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarekTEST_F(SanityCheck, NoResolver) {
159281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  stack_section.start() = 0x80000000;
1607a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  stack_section.D32(0).D32(0);  // end-of-stack marker
161281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  RegionFromSection();
162281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  raw_context.eip = 0x40000200;
163281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  raw_context.ebp = 0x80000000;
164281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek
1659753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(NULL, NULL);
166281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1679753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
168281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  // This should succeed, even without a resolver or supplier.
1695a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
1702d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
1712d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1722d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
1735a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
1745a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
1752d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
176281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  frames = call_stack.frames();
177281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
178281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  // Check that the values from the original raw context made it
179281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  // through to the context in the stack frame.
180281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
181281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek}
182281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek
183a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyclass GetContextFrame: public StackwalkerX86Fixture, public Test { };
184a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
185a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetContextFrame, Simple) {
186a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
1877a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  stack_section.D32(0).D32(0);  // end-of-stack marker
188a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
189a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.eip = 0x40000200;
190a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = 0x80000000;
191a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
1929753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
193a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
1949753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
1955a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
1962d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
1972d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
1982d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
1995a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
2005a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
2012d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
202e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  frames = call_stack.frames();
203e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
204e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // Check that the values from the original raw context made it
205e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // through to the context in the stack frame.
206e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
207e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com}
208e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
209e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// The stackwalker should be able to produce the context frame even
210e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// without stack memory present.
211e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comTEST_F(GetContextFrame, NoStackMemory) {
212e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  raw_context.eip = 0x40000200;
213e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  raw_context.ebp = 0x80000000;
214e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
215e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
216e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules,
217e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com                        &frame_symbolizer);
2185a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
2192d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
2202d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
2212d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
2225a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
2235a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
2242d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
225a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
226a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
227a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Check that the values from the original raw context made it
228a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // through to the context in the stack frame.
229281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek  EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
230a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
231a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
2322d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.comclass GetCallerFrame: public StackwalkerX86Fixture, public Test {
2332d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com protected:
2342d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  void IPAddressIsNotInKnownModuleTestImpl(bool has_corrupt_symbols);
2352d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com};
236a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
237a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Walk a traditional frame. A traditional frame saves the caller's
238a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// %ebp just below the return address, and has its own %ebp pointing
239a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// at the saved %ebp.
240a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, Traditional) {
241a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
242a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame0_ebp, frame1_ebp;
243a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
244a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(12, 0)                      // frame 0: space
245a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame0_ebp)                  // frame 0 %ebp points here
246a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(frame1_ebp)                    // frame 0: saved %ebp
247a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x40008679)                    // frame 0: return address
248a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(8, 0)                       // frame 1: space
249a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_ebp)                  // frame 1 %ebp points here
250a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0)                             // frame 1: saved %ebp (stack end)
251a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0);                            // frame 1: return address (stack end)
252a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
253a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.eip = 0x4000c7a5;
254a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
255a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = frame0_ebp.Value();
256a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
2579753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
258a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
2599753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
2605a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
2612d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
2622d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
2632d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
2645a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
2655a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
2662d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
267a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
268a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
269a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
2702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
2712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
2722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
2732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
2742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000c7a5U, frame0->instruction);
2752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
2762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
2772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame0->windows_frame_info);
2782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
2792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
2802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
2812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
2822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
2832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
2842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
2852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
2862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
2872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40008679U, frame1->instruction + 1);
2882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40008679U, frame1->context.eip);
2892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
2902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
2912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
292a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
293a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
294a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Walk a traditional frame, but use a bogus %ebp value, forcing a scan
295a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// of the stack for something that looks like a return address.
296a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, TraditionalScan) {
297a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
298a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame1_ebp;
2997a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame1_esp;
300a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
301a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0
302a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xf065dc76)    // locals area:
303a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x46ee2167)    // garbage that doesn't look like
304a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xbab023ec)    // a return address
305a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(frame1_ebp)    // saved %ebp (%ebp fails to point here, forcing scan)
306a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x4000129d)    // return address
307a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1
3087a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp)
309a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(8, 0)       // space
310a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_ebp)  // %ebp points here
311a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0)             // saved %ebp (stack end)
312a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0);            // return address (stack end)
313a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
314a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
315a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.eip = 0x4000f49d;
316a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
317a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Make the frame pointer bogus, to make the stackwalker scan the stack
318a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // for something that looks like a return address.
319a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = 0xd43eed6e;
320a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
3219753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
322a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
3239753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
3245a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
3252d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
3262d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
3272d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
3285a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
3295a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
3302d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
331a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
332a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
333a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
3342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
3352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
3362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
3372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
3382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000f49dU, frame0->instruction);
3392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000f49dU, frame0->context.eip);
3402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
3412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
3422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame0->windows_frame_info);
3432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
3442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
3452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
3462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
3472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
3482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
3492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
3502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
3512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
3522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
3532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000129dU, frame1->context.eip);
3547a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
3557a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
3562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
3572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
358a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
359a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
3609c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek// Force scanning for a return address a long way down the stack
3619c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarekTEST_F(GetCallerFrame, TraditionalScanLongWay) {
3629c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  stack_section.start() = 0x80000000;
3639c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  Label frame1_ebp;
3647a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame1_esp;
3659c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  stack_section
3669c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    // frame 0
3679c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(0xf065dc76)    // locals area:
3689c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(0x46ee2167)    // garbage that doesn't look like
3699c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(0xbab023ec)    // a return address
3709c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .Append(20 * 4, 0)  // a bunch of space
3719c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(frame1_ebp)    // saved %ebp (%ebp fails to point here, forcing scan)
3729c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(0x4000129d)    // return address
3739c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    // frame 1
3747a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp)
3759c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .Append(8, 0)       // space
3769c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .Mark(&frame1_ebp)  // %ebp points here
3779c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(0)             // saved %ebp (stack end)
3789c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek    .D32(0);            // return address (stack end)
3799c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek
3809c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  RegionFromSection();
3819c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  raw_context.eip = 0x4000f49d;
3829c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  raw_context.esp = stack_section.start().Value();
3839c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  // Make the frame pointer bogus, to make the stackwalker scan the stack
3849c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  // for something that looks like a return address.
3859c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  raw_context.ebp = 0xd43eed6e;
3869c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek
3879753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
3889c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
3899753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
3905a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
3912d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
3922d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
3932d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
3945a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
3955a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
3962d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
3979c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  frames = call_stack.frames();
3989c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek  ASSERT_EQ(2U, frames->size());
3999c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek
4002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
4012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
4022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
4032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
4042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000f49dU, frame0->instruction);
4052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000f49dU, frame0->context.eip);
4062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
4072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
4082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame0->windows_frame_info);
4092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
4102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
4112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
4122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
4132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
4142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
4152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
4162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
4172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
4182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
4192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000129dU, frame1->context.eip);
4207a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
4217a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
4222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
4232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
42442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com}
42542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com
42642b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com// Test that set_max_frames_scanned prevents using stack scanning
42742b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com// to find caller frames.
42842b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.comTEST_F(GetCallerFrame, ScanningNotAllowed) {
42942b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  stack_section.start() = 0x80000000;
43042b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  Label frame1_ebp;
43142b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  stack_section
43242b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    // frame 0
43342b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(0xf065dc76)    // locals area:
43442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(0x46ee2167)    // garbage that doesn't look like
43542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(0xbab023ec)    // a return address
43642b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(frame1_ebp)    // saved %ebp (%ebp fails to point here, forcing scan)
43742b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(0x4000129d)    // return address
43842b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    // frame 1
43942b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .Append(8, 0)       // space
44042b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .Mark(&frame1_ebp)  // %ebp points here
44142b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(0)             // saved %ebp (stack end)
44242b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    .D32(0);            // return address (stack end)
44342b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com
44442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  RegionFromSection();
44542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  raw_context.eip = 0x4000f49d;
44642b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  raw_context.esp = stack_section.start().Value();
44742b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  // Make the frame pointer bogus, to make the stackwalker scan the stack
44842b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  // for something that looks like a return address.
44942b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  raw_context.ebp = 0xd43eed6e;
45042b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com
45142b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
45242b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
45342b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com                        &frame_symbolizer);
45442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  Stackwalker::set_max_frames_scanned(0);
45542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com
45642b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  vector<const CodeModule*> modules_without_symbols;
45742b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
45842b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
45942b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com                          &modules_with_corrupt_symbols));
46042b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
46142b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
46242b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
46342b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  frames = call_stack.frames();
46442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  ASSERT_EQ(1U, frames->size());
46542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com
46642b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  {  // To avoid reusing locals by mistake
46742b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
46842b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
46942b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
47042b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    EXPECT_EQ(0x4000f49dU, frame0->instruction);
47142b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    EXPECT_EQ(0x4000f49dU, frame0->context.eip);
47242b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
47342b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
47442b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com    EXPECT_EQ(NULL, frame0->windows_frame_info);
47542b91fbbf30f8a6d900d1fb97e96394dbb363890ted.mielczarek@gmail.com  }
4769c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek}
4779c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek
478a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a
479a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a stack frame.
480a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameData) {
481a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module1,
482a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
483a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $T2 $esp .cbSavedRegs + ="
484a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $T0 .raSearchStart ="
485a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $eip $T0 ^ ="
486a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $esp $T0 4 + ="
487a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $ebx $T2 4  - ^ ="
488a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $edi $T2 8  - ^ ="
489a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $esi $T2 12 - ^ ="
490a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $ebp $T2 16 - ^ =\n");
491a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame1_esp, frame1_ebp;
492a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
493a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
494a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0
495a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(frame1_ebp)                    // saved regs: %ebp
496a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xa7120d1a)                    //             %esi
497a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x630891be)                    //             %edi
498a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x9068a878)                    //             %ebx
499a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xa08ea45f)                    // locals: unused
500a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x40001350)                    // return address
501a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1
502a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_esp)
503a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(12, 0)                      // empty space
504a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_ebp)
505a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0)                             // saved %ebp (stack end)
506a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0);                            // saved %eip (stack end)
507a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
508a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
509a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.eip = 0x4000aa85;
510a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
511a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = 0xf052c1de;         // should not be needed to walk frame
512a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
5139753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
514a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
5159753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
5165a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
5172d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
5182d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
5192d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
5205a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
5212d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
522a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
523a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
524a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
5252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
5262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
5272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
5282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
5292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000aa85U, frame0->instruction);
5302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000aa85U, frame0->context.eip);
5312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
5322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
5332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame0->windows_frame_info != NULL);
5342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
5352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
5362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
5372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
5382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
5392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
5402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
5412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP
5422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBX
5432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESI
5442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EDI),
5452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
5462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40001350U, frame1->instruction + 1);
5472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40001350U, frame1->context.eip);
5482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
5492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
5502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x9068a878U, frame1->context.ebx);
5512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0xa7120d1aU, frame1->context.esi);
5522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x630891beU, frame1->context.edi);
5532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
5542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
555a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
556a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
557a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a
5586679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org// FrameTypeFrameData DIA record) to walk a stack frame where the stack
5596679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org// is aligned and we must search
5606679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.orgTEST_F(GetCallerFrame, WindowsFrameDataAligned) {
5616679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  SetModuleSymbols(&module1,
5626679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org                   "STACK WIN 4 aa85 176 0 0 4 4 8 0 1"
5637a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   " $T1 .raSearch ="
5647a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   " $T0 $T1 4 - 8 @ ="
5657a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   " $ebp $T1 4 - ^ ="
5667a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   " $eip $T1 ^ ="
5677a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   " $esp $T1 4 + =");
56815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame0_esp, frame0_ebp;
5696679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  Label frame1_esp, frame1_ebp;
5706679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  stack_section.start() = 0x80000000;
5716679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  stack_section
5726679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    // frame 0
57315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame0_esp)
5746679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0x0ffa0ffa)                    // unused saved register
5756679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0xdeaddead)                    // locals
5766679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0xbeefbeef)
5776679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0)                             // 8-byte alignment
57815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame0_ebp)
57915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(frame1_ebp)                    // saved %ebp
5806679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0x5000129d)                    // return address
5816679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    // frame 1
5826679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .Mark(&frame1_esp)
5836679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0x1)                           // parameter
5846679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .Mark(&frame1_ebp)
5856679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0)                             // saved %ebp (stack end)
5866679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org    .D32(0);                            // saved %eip (stack end)
5876679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org
5886679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  RegionFromSection();
5896679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  raw_context.eip = 0x4000aa85;
59015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  raw_context.esp = frame0_esp.Value();
59115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  raw_context.ebp = frame0_ebp.Value();
5926679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org
5939753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
5946679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
5959753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
5965a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
5972d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
5982d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
5992d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
6005a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(1U, modules_without_symbols.size());
6015a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
6022d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
6036679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  frames = call_stack.frames();
6046679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org  ASSERT_EQ(2U, frames->size());
6056679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org
6062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
6072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
6082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
6092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
6102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000aa85U, frame0->instruction);
6112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000aa85U, frame0->context.eip);
61215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
61315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
6142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame0->windows_frame_info != NULL);
6152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
6162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
6172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
6182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
6192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
6202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
6212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
6222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
6232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
6242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000129dU, frame1->instruction + 1);
6252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000129dU, frame1->context.eip);
6262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
6272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
6282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
6292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
6306679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org}
6316679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org
6326679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org// Use Windows frame data (a "STACK WIN 4" record, from a
633a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a frame, and depend on the
634a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// parameter size from the callee as well.
635a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
636a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n");
637a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module2,
6386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                   // Note bogus parameter size in FUNC record; the stack walker
6396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                   // should prefer the STACK WIN record, and see '4' below.
640a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "FUNC aa85 176 beef module2::whine\n"
641a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
642a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $T2 $esp .cbLocals + .cbSavedRegs + ="
643a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $T0 .raSearchStart ="
644a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $eip $T0 ^ ="
645a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $esp $T0 4 + ="
646a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $ebp $T0 20 - ^ ="
647a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $ebx $T0 8 - ^ =\n");
648a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame0_esp, frame0_ebp;
649a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame1_esp;
650a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame2_esp, frame2_ebp;
651a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
652a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
653a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0, in module1::wheedle.  Traditional frame.
654a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame0_esp)
655a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(16, 0)      // frame space
656a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame0_ebp)
657a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x6fa902e0)    // saved %ebp.  Not a frame pointer.
658a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x5000aa95)    // return address, in module2::whine
659a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1, in module2::whine.  FrameData frame.
660a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_esp)
661a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xbaa0cb7a)    // argument 3 passed to module1::wheedle
662a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xbdc92f9f)    // argument 2
663a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x0b1d8442)    // argument 1
664a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(frame2_ebp)    // saved %ebp
665a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xb1b90a15)    // unused
666a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xf18e072d)    // unused
667a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x2558c7f3)    // saved %ebx
668a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x0365e25e)    // unused
669a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x2a179e38)    // return address; $T0 points here
670a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 2, in no module
671a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame2_esp)
672a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(12, 0)      // empty space
673a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame2_ebp)
674a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0)             // saved %ebp (stack end)
675a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0);            // saved %eip (stack end)
676a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
677a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
6787a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.eip = 0x40001004;  // in module1::wheedle
679a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
680a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = frame0_ebp.Value();
681a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
6829753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
683a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
6849753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
6855a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
6862d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
6872d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
6882d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
6895a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
6902d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
691a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
692a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(3U, frames->size());
693a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
6942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
6952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
6962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
6972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
6982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40001004U, frame0->instruction);
6992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40001004U, frame0->context.eip);
7002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
7012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
7022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module1, frame0->module);
7032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("module1::wheedle", frame0->function_name);
7042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40001000U, frame0->function_base);
7052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // The FUNC record for module1::wheedle should have produced a
7062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // WindowsFrameInfo structure with only the parameter size valid.
7072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_TRUE(frame0->windows_frame_info != NULL);
7082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
7092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame0->windows_frame_info->valid);
7102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN,
7112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame0->windows_frame_info->type_);
7122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
7132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
7142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
7152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
7162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
7172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
7182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
7192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
7202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
7212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
7222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000aa95U, frame1->instruction + 1);
7232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000aa95U, frame1->context.eip);
7242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
7252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x6fa902e0U, frame1->context.ebp);
7262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module2, frame1->module);
7272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("module2::whine", frame1->function_name);
7282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000aa85U, frame1->function_base);
7292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_TRUE(frame1->windows_frame_info != NULL);
7302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
7312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
7322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->windows_frame_info->type_);
7332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // This should not see the 0xbeef parameter size from the FUNC
7342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // record, but should instead see the STACK WIN record.
7352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
7362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
7372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
7382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
7392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
7402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
7412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
7422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
7432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP
7442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBX),
7452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame2->context_validity);
7462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x2a179e38U, frame2->instruction + 1);
7472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x2a179e38U, frame2->context.eip);
7482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
7492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
7502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x2558c7f3U, frame2->context.ebx);
7512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame2->module);
7522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame2->windows_frame_info);
7532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
754a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
755a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
756a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a
757a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a stack frame, where the
7586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// expression fails to yield both an $eip and an $ebp value, and the stack
7596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// walker must scan.
760a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameDataScan) {
761a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module1,
762a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n");
763a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Mark frame 1's PC as the end of the stack.
764a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module2,
765a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "FUNC 7c38 accf 0 module2::function\n"
766a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n");
767a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame1_esp;
768a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
769a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
770a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0
771a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(16, 0x2a)                   // unused, garbage
772a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x50007ce9)                    // return address
773a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1
774a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_esp)
775a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(8, 0);                      // empty space
776a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
777a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
778a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.eip = 0x40000c9c;
779a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
780a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = 0x2ae314cd;         // should not be needed to walk frame
781a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
7829753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
783a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
7849753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
7855a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
7862d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
7872d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
7882d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
7895a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
7902d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
791a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
792a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
793a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
7942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
7952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
7962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
7972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
7982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40000c9cU, frame0->instruction);
7992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40000c9cU, frame0->context.eip);
8002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
8012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x2ae314cdU, frame0->context.ebp);
8022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame0->windows_frame_info != NULL);
8032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
8042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
8052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
8062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
8072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
8082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
8092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // does not actually fetch the EBP after a scan (forcing the next frame
8102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // to be scanned as well). But let's grandfather the existing behavior in
8112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // for now.
8122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
8132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
8142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
8152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
8162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x50007ce9U, frame1->instruction + 1);
8172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x50007ce9U, frame1->context.eip);
8182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
8192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame1->windows_frame_info != NULL);
8202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
821a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
822a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
823a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a
824a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a stack frame, where the
8256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// expression yields an $eip that falls outside of any module, and the
8266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// stack walker must scan.
827a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
828a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module1,
829a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1"
830a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   // A traditional frame, actually.
831a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n");
832a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Mark frame 1's PC as the end of the stack.
833a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module2,
834a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "FUNC cfdb 8406 0 module2::function\n"
835a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n");
836a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
837a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
838a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // In this stack, the context's %ebp is pointing at the wrong place, so
8396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // the stack walker needs to scan to find the return address, and then
8406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // scan again to find the caller's saved %ebp.
841a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame0_ebp, frame1_ebp, frame1_esp;
842a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
843a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0
844a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Append(8, 0x2a)            // garbage
845a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame0_ebp)          // frame 0 %ebp points here, but should point
846a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                                // at *** below
847a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // The STACK WIN record says that the following two values are
848a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1's saved %ebp and return address, but the %ebp is wrong;
8496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // they're garbage. The stack walker will scan for the right values.
850a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x3d937b2b)            // alleged to be frame 1's saved %ebp
851a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x17847f5b)            // alleged to be frame 1's return address
852a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(frame1_ebp)            // frame 1's real saved %ebp; scan will find
853a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x2b2b2b2b)            // first word of realigned register save area
854a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // *** frame 0 %ebp ought to be pointing here
855a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x2c2c2c2c)            // realigned locals area
856a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x5000d000)            // frame 1's real saved %eip; scan will find
857a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // Frame 1, in module2::function. The STACK WIN record describes
858a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // this as the oldest frame, without referring to its contents, so
8596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // we needn't to provide any actual data here.
860a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_esp)
861a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_ebp)          // frame 1 %ebp points here
862a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // A dummy value for frame 1's %ebp to point at. The scan recognizes the
863a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // saved %ebp because it points to a valid word in the stack memory region.
864a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x2d2d2d2d);
865a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
866a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
867a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.eip = 0x40000700;
868a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
869a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = frame0_ebp.Value();
870a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
8719753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
872a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
8739753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
8745a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
8752d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
8762d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
8772d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
8785a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
8792d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
880a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
881a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
882a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
8832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
8842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
8852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
8862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
8872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40000700U, frame0->instruction);
8882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40000700U, frame0->context.eip);
8892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
8902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
8912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame0->windows_frame_info != NULL);
8922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
8932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
8942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
8952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
8962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
8972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
8982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // walker does not actually fetch the EBP after a scan (forcing the
8992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // next frame to be scanned as well). But let's grandfather the existing
9002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // behavior in for now.
9012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
9022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
9032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
9042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
9052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000d000U, frame1->instruction + 1);
9062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x5000d000U, frame1->context.eip);
9072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
9082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
9092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame1->windows_frame_info != NULL);
9102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
911a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
912a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
913a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows FrameTypeFPO data to walk a stack frame for a function that
914a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// does not modify %ebp from the value it had in the caller.
915a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
916a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module1,
9176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                   // Note bogus parameter size in FUNC record; the walker
9186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                   // should prefer the STACK WIN record, and see the '8' below.
919a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "FUNC e8a8 100 feeb module1::discombobulated\n"
920a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n");
921a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame0_esp;
922a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame1_esp, frame1_ebp;
923a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
924a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
925a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0, in module1::wheedle.  FrameTypeFPO (STACK WIN 0) frame.
926a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame0_esp)
927a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // no outgoing parameters; this is the youngest frame.
9287a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x7c521352)     // four bytes of saved registers
9297a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Append(0x10, 0x42)  // local area
9307a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x40009b5b)     // return address, in module1, no function
931a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1, in module1, no function.
932a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_esp)
9337a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xf60ea7fc)     // junk
934a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_ebp)
9357a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0)              // saved %ebp (stack end)
9367a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0);             // saved %eip (stack end)
937a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
938a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
9397a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.eip = 0x4000e8b8;  // in module1::whine
940a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
941a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // Frame pointer unchanged from caller.
942a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = frame1_ebp.Value();
943a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
9449753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
945a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
9469753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
9475a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
9482d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
9492d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
9502d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
9515a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
9522d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
953a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
954a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
955a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
9562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
9572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
9582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
9592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
9602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000e8b8U, frame0->instruction);
9612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
9622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
9637a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    // unchanged from caller
9647a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
9652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module1, frame0->module);
9662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("module1::discombobulated", frame0->function_name);
9672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000e8a8U, frame0->function_base);
9682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // The STACK WIN record for module1::discombobulated should have
9692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // produced a fully populated WindowsFrameInfo structure.
9702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_TRUE(frame0->windows_frame_info != NULL);
9712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
9722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
9732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame0->windows_frame_info->type_);
9742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
9752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
9762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
9772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
9782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
9792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
9802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
9812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
9822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
9832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
9842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40009b5bU, frame1->instruction + 1);
9852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40009b5bU, frame1->context.eip);
9862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
9872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
9882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module1, frame1->module);
9892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("", frame1->function_name);
9902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
9912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
992a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
993a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
994a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows FrameTypeFPO data to walk a stack frame for a function
995a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// that uses %ebp for its own purposes, saving the value it had in the
996a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// caller in the standard place in the saved register area.
997a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
998a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  SetModuleSymbols(&module1,
9996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                   // Note bogus parameter size in FUNC record; the walker
10006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                   // should prefer the STACK WIN record, and see the '8' below.
1001a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n"
1002a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy                   "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n");
1003a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame0_esp;
1004a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  Label frame1_esp, frame1_ebp;
1005a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section.start() = 0x80000000;
1006a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  stack_section
1007a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 0, in module1::wheedle.  FrameTypeFPO (STACK WIN 0) frame.
1008a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame0_esp)
1009a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // no outgoing parameters; this is the youngest frame.
1010a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(frame1_ebp)    // saved register area: saved %ebp
1011a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xb68bd5f9)    // saved register area: something else
1012a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xd25d05fc)    // local area
1013a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0x4000debe)    // return address, in module1, no function
1014a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    // frame 1, in module1, no function.
1015a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_esp)
1016a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0xf0c9a974)    // junk
1017a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .Mark(&frame1_ebp)
1018a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0)             // saved %ebp (stack end)
1019a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy    .D32(0);            // saved %eip (stack end)
1020a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
1021a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  RegionFromSection();
10227a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.eip = 0x40009ab8;  // in module1::RaisedByTheAliens
1023a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.esp = stack_section.start().Value();
1024a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  // RaisedByTheAliens uses %ebp for its own mysterious purposes.
1025a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  raw_context.ebp = 0xecbdd1a5;
1026a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
10279753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
1028a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
10299753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
10305a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
10312d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
10322d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
10332d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
10345a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
10352d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
1036a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  frames = call_stack.frames();
1037a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy  ASSERT_EQ(2U, frames->size());
1038a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy
10392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
10402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
10412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
10422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
10432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40009ab8U, frame0->instruction);
10442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40009ab8U, frame0->context.eip);
10452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
10462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0xecbdd1a5, frame0->context.ebp);
10472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module1, frame0->module);
10482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name);
10492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x40009aa8U, frame0->function_base);
10502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // The STACK WIN record for module1::RaisedByTheAliens should have
10512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // produced a fully populated WindowsFrameInfo structure.
10522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_TRUE(frame0->windows_frame_info != NULL);
10532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
10542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
10552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame0->windows_frame_info->type_);
10562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("", frame0->windows_frame_info->program_string);
10572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
10582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
10592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
10602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
10612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
10622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
10632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
10642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
10652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
10662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
10672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000debeU, frame1->instruction + 1);
10682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x4000debeU, frame1->context.eip);
10692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
10702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
10712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module1, frame1->module);
10722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("", frame1->function_name);
10732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(NULL, frame1->windows_frame_info);
10742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
10752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com}
10762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
10772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// This is a regression unit test which covers a bug which has to do with
10782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// FPO-optimized Windows system call stubs in the context frame.  There is
10792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// a more recent Windows system call dispatch mechanism which differs from
10802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// the one which is being tested here.  The newer system call dispatch
10812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// mechanism creates an extra context frame (KiFastSystemCallRet).
10822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.comTEST_F(GetCallerFrame, WindowsFPOSystemCall) {
10832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  SetModuleSymbols(&module3,  // ntdll.dll
10842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "PUBLIC 1f8ac c ZwWaitForSingleObject\n"
10852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n");
10862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  SetModuleSymbols(&module4,  // kernelbase.dll
10872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "PUBLIC 109f9 c WaitForSingleObjectEx\n"
10882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "PUBLIC 36590 0 _except_handler4\n"
10892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip "
10902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
10912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
10922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip "
10932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 "
10942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
10952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  SetModuleSymbols(&module5,  // kernel32.dll
10962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "PUBLIC 11136 8 WaitForSingleObject\n"
10972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "PUBLIC 11151 c WaitForSingleObjectExImplementation\n"
10982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip "
10992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
11002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
11012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip "
11022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
11032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
11042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  SetModuleSymbols(&module6,  // chrome.dll
11052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "FILE 7038 some_file_name.h\n"
11062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "FILE 839776 some_file_name.cc\n"
11072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "FUNC 217fda 17 4 function_217fda\n"
11082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "217fda 4 102 839776\n"
11092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "FUNC 217ff1 a 4 function_217ff1\n"
11102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "217ff1 0 594 7038\n"
11112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "217ff1 a 596 7038\n"
11122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                   "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n");
11132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
11142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  Label frame0_esp, frame1_esp;
11152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  Label frame1_ebp, frame2_ebp, frame3_ebp;
11162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  stack_section.start() = 0x002ff290;
11172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  stack_section
11182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .Mark(&frame0_esp)
11192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x771ef8c1)    // EIP in frame 0 (system call)
11202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x75fa0a91)    // return address of frame 0
11212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .Mark(&frame1_esp)
11222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x000017b0)    // args to child
11232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x002ff2d8)
11252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x88014a2e)
11262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x002ff364)
11272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x000017b0)
11282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000024)
11302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000001)
11312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x9e3b9800)
11392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0xfffffff7)
11402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x002ff2a4)
11422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x64a07ff1)    // random value to be confused with a return address
11432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x002ff8dc)
11442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x75fc6590)    // random value to be confused with a return address
11452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0xfdd2c6ea)
11462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .Mark(&frame1_ebp)
11482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(frame2_ebp)    // Child EBP
11492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x75741194)    // return address of frame 1
11502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x000017b0)    // args to child
11512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x0036ee80)
11522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x65bc7d14)
11542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .Mark(&frame2_ebp)
11552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(frame3_ebp)    // Child EBP
11562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x75741148)    // return address of frame 2
11572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x000017b0)    // args to child
11582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x0036ee80)
11592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0x00000000)
11602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .Mark(&frame3_ebp)
11612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0)             // saved %ebp (stack end)
11622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    .D32(0);            // saved %eip (stack end)
11632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
11642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  RegionFromSection();
11652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  raw_context.eip = 0x771ef8c1;  // in ntdll::ZwWaitForSingleObject
11662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  raw_context.esp = stack_section.start().Value();
11672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  ASSERT_TRUE(raw_context.esp == frame0_esp.Value());
11682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  raw_context.ebp = frame1_ebp.Value();
11692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
11709753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
11712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
11729753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                        &frame_symbolizer);
11735a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
11742d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
11752d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
11762d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
11775a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
11782d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
11792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  frames = call_stack.frames();
11802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
11812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  ASSERT_EQ(4U, frames->size());
11822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
11832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
11842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
11852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
11862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
11872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x771ef8c1U, frame0->instruction);
11882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x771ef8c1U, frame0->context.eip);
11892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
11902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
11912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module3, frame0->module);
11922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name);
11932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // The STACK WIN record for module3!ZwWaitForSingleObject should have
11942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // produced a fully populated WindowsFrameInfo structure.
11952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_TRUE(frame0->windows_frame_info != NULL);
11962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
11972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
11982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame0->windows_frame_info->type_);
11992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("", frame0->windows_frame_info->program_string);
12002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
12012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
12022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
12032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
12042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
12052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
12062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
12072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_ESP
12082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com               | StackFrameX86::CONTEXT_VALID_EBP),
12092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->context_validity);
12102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1);
12112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(0x75fa0a91U, frame1->context.eip);
12122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
12132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
12142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(&module4, frame1->module);
12152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name);
12162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // The STACK WIN record for module4!WaitForSingleObjectEx should have
12172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    // produced a fully populated WindowsFrameInfo structure.
12182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    ASSERT_TRUE(frame1->windows_frame_info != NULL);
12192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
12202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
12212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->windows_frame_info->type_);
12222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
12232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =",
12242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com              frame1->windows_frame_info->program_string);
12252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
12262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com  }
1227a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}
12286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
12293108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// Scan the stack for a better return address and potentially skip frames
12307a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// when the calculated return address is not in a known module.  Note, that
12317a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// the span of this scan is somewhat arbitrarily limited to 120 search words
12327a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// for the context frame and 30 search words (pointers) for the other frames:
12333108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com//     const int kRASearchWords = 30;
12343108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// This means that frames can be skipped only when their size is relatively
12357a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// small: smaller than 4 * kRASearchWords * sizeof(InstructionType)
12363108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.comTEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) {
12373108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1");
12383108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  SetModuleSymbols(&msvcrt_dll,  // msvcrt.dll
12393108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "PUBLIC 38180 0 wcsstr\n"
12403108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 "
12413108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
12423108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "- = $P $T0 4 + .cbParams + =\n");
12433108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
12443108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1");
12453108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  SetModuleSymbols(&kernel32_dll,  // kernel32.dll
12463108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "PUBLIC efda 8 FindNextFileW\n"
12473108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 "
12483108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
12493108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "- = $P $T0 4 + .cbParams + =\n");
12503108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
12513108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1");
12523108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  SetModuleSymbols(&chrome_dll,  // chrome.dll
12533108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n"
12543108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "e3cff 1a 711 2505\n"
12553108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = "
12563108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "$T0  $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
12573108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "$T1 4 + = $20 $T0 152 - ^ =  $23 $T0 156 - ^ =  $24 "
12583108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                   "$T0 160 - ^ =\n");
12593108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
12603108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  // Create some modules with some stock debugging information.
12613108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  MockCodeModules local_modules;
12623108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  local_modules.Add(&msvcrt_dll);
12633108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  local_modules.Add(&kernel32_dll);
12643108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  local_modules.Add(&chrome_dll);
12653108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
12663108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  Label frame0_esp;
12673108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  Label frame0_ebp;
12683108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  Label frame1_ebp;
12693108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  Label frame2_ebp;
12703108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  Label frame3_ebp;
12713108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
12723108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  stack_section.start() = 0x0932f2d0;
12733108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  stack_section
12743108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .Mark(&frame0_esp)
12753108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e000)
12763108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e068)
12773108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .Mark(&frame0_ebp)
12783108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(frame1_ebp)    // Child EBP
12793108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x001767a0)    // return address of frame 0
12803108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                        // Not in known module
12813108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e0c6)
12823108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x001bb1b8)
12833108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e068)
12843108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000003)
12853108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e068)
12863108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000003)
12873108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x07578828)
12883108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e000)
12893108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
12903108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x001c0010)
12913108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e0c6)
12923108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .Mark(&frame1_ebp)
12933108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(frame2_ebp)    // Child EBP
12943108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x7c80f10f)    // return address of frame 1
12953108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                        // inside kernel32!FindNextFileW
12963108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x000008f8)
12973108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
12983108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
12993108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13003108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f34c)
13013108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e000)
13023108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00001000)
13033108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13043108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000001)
13053108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13063108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13073108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f6a8)
13083108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13093108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f6d8)
13103108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13113108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x000000d6)
13123108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0764e000)
13133108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x7ff9a000)
13143108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f3fc)
13153108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000001)
13163108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000001)
13173108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x07578828)
13183108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0000002e)
13193108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f340)
13203108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932eef4)
13213108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932ffdc)
13223108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x7c839ad8)
13233108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x7c80f0d8)
13243108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13253108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .Mark(&frame2_ebp)
13263108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(frame3_ebp)    // Child EBP
13273108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x01d13f91)    // return address of frame 2
13283108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                        // inside chrome_dll!file_util::FileEnumerator::Next
13293108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x07578828)
13303108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f6ac)
13313108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f9c4)
13323108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f9b4)
13333108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13343108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000003)
13353108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f978)
13363108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x01094330)
13373108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13383108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000001)
13393108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x01094330)
13403108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13413108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13423108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x07f30000)
13433108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x01c3ba17)
13443108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x08bab840)
13453108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x07f31580)
13463108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13473108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000007)
13483108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f940)
13493108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0000002e)
13503108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f40c)
13513108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x01d13b53)
13523108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f958)
13533108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000001)
13543108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000007)
13553108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f940)
13563108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0000002e)
13573108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13583108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f6ac)
13593108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x01e13ef0)
13603108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000001)
13613108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000007)
13623108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f958)
13633108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x08bab840)
13643108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f9b4)
13653108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x00000000)
13663108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f9b4)
13673108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x000000a7)
13683108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x000000a7)
13693108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x0932f998)
13703108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0x579627a2)
13713108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .Mark(&frame3_ebp)
13723108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0)             // saved %ebp (stack end)
13733108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    .D32(0);            // saved %eip (stack end)
13743108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
13753108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  RegionFromSection();
13763108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  raw_context.eip = 0x77c181cd;  // inside msvcrt!wcsstr
13773108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  raw_context.esp = frame0_esp.Value();
13783108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  raw_context.ebp = frame0_ebp.Value();
13793108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  // sanity
13803108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
13813108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8);
13823108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
13833108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
13843108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
13853108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com                        &local_modules, &frame_symbolizer);
13865a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
13872d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
13882d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
13892d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
13905a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
13912d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
13923108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  frames = call_stack.frames();
13933108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
13943108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  ASSERT_EQ(3U, frames->size());
13953108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
13963108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
13973108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
13983108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
13993108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
14003108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(0x77c181cdU, frame0->instruction);
14013108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(0x77c181cdU, frame0->context.eip);
14023108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
14033108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
14043108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(&msvcrt_dll, frame0->module);
14053108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ("wcsstr", frame0->function_name);
14063108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    ASSERT_TRUE(frame0->windows_frame_info != NULL);
14073108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
14083108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
14093108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame0->windows_frame_info->type_);
14103108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 "
14113108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
14123108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "- = $P $T0 4 + .cbParams + =",
14133108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame0->windows_frame_info->program_string);
14143108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    // It has program string, so allocates_base_pointer is not expected
14153108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
14163108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  }
14173108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
14183108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
14193108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
14203108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
14213108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
14223108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
14233108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
14243108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame1->context_validity);
14253108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1);
14263108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(0x7c80f10fU, frame1->context.eip);
14273108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp.
14283108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp);
14293108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(&kernel32_dll, frame1->module);
14303108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ("FindNextFileW", frame1->function_name);
14313108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    ASSERT_TRUE(frame1->windows_frame_info != NULL);
14323108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
14333108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
14343108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame1->windows_frame_info->type_);
14353108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 "
14363108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
14373108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "- = $P $T0 4 + .cbParams + =",
14383108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame1->windows_frame_info->program_string);
14393108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
14403108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  }
14413108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
14423108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
14433108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
14443108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
14453108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
14463108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
14473108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
14483108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame2->context_validity);
14493108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(0x01d13f91U, frame2->instruction + 1);
14503108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(0x01d13f91U, frame2->context.eip);
14513108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp.
14523108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp);
14533108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(&chrome_dll, frame2->module);
14543108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name);
14553108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    ASSERT_TRUE(frame2->windows_frame_info != NULL);
14563108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
14573108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
14583108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame2->windows_frame_info->type_);
14593108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_EQ("$T1 .raSearch = "
14603108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "$T0  $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
14613108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "$T1 4 + = $20 $T0 152 - ^ =  $23 $T0 156 - ^ =  $24 "
14623108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              "$T0 160 - ^ =",
14633108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com              frame2->windows_frame_info->program_string);
14643108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com    EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
14653108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com  }
14663108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com}
14673108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com
146815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com// Test the .raSearchStart/.raSearch calculation when alignment operators are
146915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com// used in the program string.  The current %ebp must be valid and it is the
147015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com// only reliable data point that can be used for that calculation.
147115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.comTEST_F(GetCallerFrame, HandleAlignmentInProgramString) {
147215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  MockCodeModule chrome_dll(0x59630000, 0x19e3000, "chrome.dll", "version1");
147315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  SetModuleSymbols(&chrome_dll,  // chrome.dll
147415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "FUNC 56422 50c 8 base::MessageLoop::RunTask"
147515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "(base::PendingTask const &)\n"
147615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "56422 e 458 4589\n"
147715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "STACK WIN 4 56422 50c 11 0 8 c ac 0 1 $T1 .raSearch = $T0 "
147815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
147915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$20 $T0 176 - ^ =  $23 $T0 180 - ^ =  $24 $T0 184 - ^ =\n"
148015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "FUNC 55d34 34a 0 base::MessageLoop::DoWork()\n"
148115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "55d34 11 596 4589\n"
148215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "STACK WIN 4 55d34 34a 19 0 0 c 134 0 1 $T1 .raSearch = "
148315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$T0  $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
148415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$T1 4 + = $20 $T0 312 - ^ =  $23 $T0 316 - ^ =  $24 $T0 "
148515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "320 - ^ =\n"
148615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "FUNC 55c39 fb 0 base::MessagePumpForIO::DoRunLoop()\n"
148715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "55c39 d 518 19962\n"
148815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "STACK WIN 4 55c39 fb d 0 0 c 34 0 1 $T1 .raSearch = $T0 "
148915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + "
149015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "= $20 $T0 56 - ^ =  $23 $T0 60 - ^ =  $24 $T0 64 - ^ =\n"
149115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "FUNC 55bf0 49 4 base::MessagePumpWin::Run(base::"
149215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "MessagePump::Delegate *)\n"
149315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "55bf0 49 48 4724\n"
149415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "STACK WIN 4 55bf0 49 c 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 "
149515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "+ ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
149615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "FUNC 165d de 4 malloc\n"
149715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "165d 6 119 54\n"
149815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "STACK WIN 4 165d de d 0 4 8 0 0 1 $T1 .raSearch = $T0 "
149915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 "
150015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "+ = $23 $T0 4 - ^ =  $24 $T0 8 - ^ =\n"
150115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "FUNC 55ac9 79 0 base::MessageLoop::RunInternal()\n"
150215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "55ac9 d 427 4589\n"
150315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "STACK WIN 4 55ac9 79 d 0 0 8 10 0 1 $T1 .raSearch = $T0 "
150415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
150515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                   "$23 $T0 20 - ^ =  $24 $T0 24 - ^ =\n");
150615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
150715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  // Create some modules with some stock debugging information.
150815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  MockCodeModules local_modules;
150915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  local_modules.Add(&chrome_dll);
151015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
151115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame0_esp;
151215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame0_ebp;
151315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame1_esp;
151415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame1_ebp;
151515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame2_esp;
151615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame2_ebp;
151715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame3_esp;
151815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  Label frame3_ebp;
151915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
152015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  stack_section.start() = 0x046bfc80;
152115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  stack_section
152215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0)
152315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame0_esp)
152415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e235a0)
152515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
152615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e9f580)
152715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e9f580)
152815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000020)
152915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
153015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00463674)
153115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000020)
153215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
153315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfcd8)
153415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfcd8)
153515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x0001204b)
153615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
153715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0xfdddb523)
153815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
153915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000007)
154015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000040)
154115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
154215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x59631693)  // chrome_59630000!malloc+0x36
154315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e9f580)
154415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e9f580)
154515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfcf8)
154615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x77da6704)  // ntdll!NtSetIoCompletion+0xc
154715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfd4c)
154815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x59685bec)  // chrome_59630000!base::MessageLoop::StartHistogrammer..
154915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e235a0)
155015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
155115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame0_ebp)
155215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(frame1_ebp)  // Child EBP    .D32(0x046bfd0c)
155315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x59685c2e)  // Return address in
155415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                      // chrome_59630000!base::MessagePumpWin::Run+0x3e
155515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame1_esp)
155615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e75a90)
155715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfd4c)
155815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e75a90)
155915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
156015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000300)
156115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000001)
156215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
156315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame1_ebp)
156415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(frame2_ebp)  // Child EBP    .D32(0x046bfd30)
156515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x59685b3c)  // Return address in
156615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                      // chrome_59630000!base::MessageLoop::RunInternal+0x73
156715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame2_esp)
156815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e75a90)
156915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x00000000)
157015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfd4c)
157115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x59658123)  // chrome_59630000!std::deque..
157215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfda0)
157315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x01e79d70)
157415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0x046bfda0)
157515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
157615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .Mark(&frame2_ebp)  // .D32(0x046bfd40)
157715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0)             // saved %ebp (stack end)
157815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    .D32(0);            // saved %eip (stack end)
157915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
158015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  RegionFromSection();
158115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  raw_context.eip = 0x59685c46;  // Context frame in
158215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                                 // base::MessagePumpForIO::DoRunLoop
158315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  raw_context.esp = frame0_esp.Value();
158415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  raw_context.ebp = frame0_ebp.Value();
158515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
158615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
158715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
158815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                        &local_modules, &frame_symbolizer);
158915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
159015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
159115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
159215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
159315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
159415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
159515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  frames = call_stack.frames();
159615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
159715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  ASSERT_EQ(3U, frames->size());
159815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
159915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
160015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
160115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust);
160215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame->context_validity);
160315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ("base::MessagePumpForIO::DoRunLoop()", frame->function_name);
160415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(0x59685c46U, frame->instruction);
160515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(0x59685c46U, frame->context.eip);
160615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame0_esp.Value(), frame->context.esp);
160715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame0_ebp.Value(), frame->context.ebp);
160815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(&chrome_dll, frame->module);
160915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    ASSERT_TRUE(frame->windows_frame_info != NULL);
161015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
161115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
161215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->windows_frame_info->type_);
161315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ("$T1 .raSearch = $T0 "
161415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + "
161515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              "= $20 $T0 56 - ^ =  $23 $T0 60 - ^ =  $24 $T0 64 - ^ =",
161615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->windows_frame_info->program_string);
161715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
161815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  }
161915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
162015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
162115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(1));
162215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
162315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
162415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
162515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
162615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->context_validity);
162715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ("base::MessagePumpWin::Run(base::MessagePump::Delegate *)",
162815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->function_name);
162915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(1500011566U, frame->instruction + 1);
163015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(1500011566U, frame->context.eip);
163115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame->context.esp);
163215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame->context.ebp);
163315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(&chrome_dll, frame->module);
163415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    ASSERT_TRUE(frame->windows_frame_info != NULL);
163515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
163615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
163715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->windows_frame_info->type_);
163815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
163915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->windows_frame_info->program_string);
164015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
164115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  }
164215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
164315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
164415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(2));
164515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
164615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
164715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
164815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
164915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->context_validity);
165015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ("base::MessageLoop::RunInternal()", frame->function_name);
165115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(1500011324U, frame->instruction + 1);
165215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(1500011324U, frame->context.eip);
165315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame2_esp.Value(), frame->context.esp);
165415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(frame2_ebp.Value(), frame->context.ebp);
165515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(&chrome_dll, frame->module);
165615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    ASSERT_TRUE(frame->windows_frame_info != NULL);
165715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
165815c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
165915c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->windows_frame_info->type_);
166015c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_EQ("$T1 .raSearch = $T0 "
166115c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
166215c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              "$23 $T0 20 - ^ =  $24 $T0 24 - ^ =",
166315c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com              frame->windows_frame_info->program_string);
166415c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com    EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
166515c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com  }
166615c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com}
166715c17c68b68d60ba9736e49d0b4a46a2affbeaf7ivan.penkov@gmail.com
16687a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// Scan the stack for a return address and potentially skip frames when the
16697a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// current IP address is not in a known module.  Note, that that the span of
16707a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// this scan is limited to 120 search words for the context frame and 30
16717a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com// search words (pointers) for the other frames:
16727a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com//     const int kRASearchWords = 30;
16732d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.comvoid GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl(
16742d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    bool has_corrupt_symbols) {
16757a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  MockCodeModule remoting_core_dll(0x54080000, 0x501000, "remoting_core.dll",
16767a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                                   "version1");
16772d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  string symbols_func_section =
16782d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      "FUNC 137214 17d 10 PK11_Verify\n"
16792d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      "FUNC 15c834 37 14 nsc_ECDSAVerifyStub\n"
16802d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      "FUNC 1611d3 91 14 NSC_Verify\n"
16812d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      "FUNC 162ff7 60 4 sftk_SessionFromHandle\n";
16822d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  string symbols_stack_section =
16837a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "STACK WIN 4 137214 17d 9 0 10 0 10 0 1 $T0 $ebp = "
16847a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
16857a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "STACK WIN 4 15c834 37 6 0 14 0 18 0 1 $T0 $ebp = "
16867a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
16877a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "STACK WIN 4 1611d3 91 7 0 14 0 8 0 1 $T0 $ebp = "
16887a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
16897a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                   "STACK WIN 4 162ff7 60 5 0 4 0 0 0 1 $T0 $ebp = "
16902d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n";
16912d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com
16922d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  string symbols = symbols_func_section;
16932d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (has_corrupt_symbols) {
16942d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    symbols.append(string(1, '\0'));           // null terminator in the middle
16952d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    symbols.append("\n");
16962d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    symbols.append("FUNC 1234\n"               // invalid FUNC records
16972d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   "FUNNC 1234\n"
16982d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   "STACK WIN 4 1234 234 23 "  // invalid STACK record
16992d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   "23423423 234 23 234 234 "
17002d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   "234 23 234 23 234 234 "
17012d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   "234 234 234\n");
17022d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  }
17032d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  symbols.append(symbols_stack_section);
17042d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  SetModuleSymbols(&remoting_core_dll, symbols);
17057a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
17067a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  // Create some modules with some stock debugging information.
17077a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  MockCodeModules local_modules;
17087a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  local_modules.Add(&remoting_core_dll);
17097a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
17107a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame0_esp;
17117a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame0_ebp;
17127a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame1_ebp;
17137a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame1_esp;
17147a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame2_ebp;
17157a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame2_esp;
17167a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame3_ebp;
17177a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label frame3_esp;
17187a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label bogus_stack_location_1;
17197a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label bogus_stack_location_2;
17207a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  Label bogus_stack_location_3;
17217a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
17227a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  stack_section.start() = 0x01a3ea28;
17237a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  stack_section
17247a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame0_esp)
17257a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(bogus_stack_location_2)
17267a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(bogus_stack_location_1)
17277a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x042478e4)
17287a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(bogus_stack_location_2)
17297a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17307a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x041f0420)
17317a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17327a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17337a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17347a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000001)
17357a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b7e0d0)
17367a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17377a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17387a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000001)
17397a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b7f570)
17407a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&bogus_stack_location_1)
17417a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17427a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17437a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000008)
17447a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04289530)
17457a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17467a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17477a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000008)
17487a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b7e910)
17497a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17507a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17517a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000008)
17527a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b7d998)
17537a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17547a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17557a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000008)
17567a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b7dec0)
17577a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&bogus_stack_location_2)
17587a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17597a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17607a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000008)
17617a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04289428)
17627a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17637a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17647a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000008)
17657a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b7f258)
17667a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&bogus_stack_location_3)
17677a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
17687a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x041f3560)
17697a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000041)
17707a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000020)
17717a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xffffffff)
17727a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame0_ebp)
17737a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(frame1_ebp)  // Child %ebp
17747a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x541dc866)  // return address of frame 0
17757a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                      // inside remoting_core!nsc_ECDSAVerifyStub+0x32
17767a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp)
17777a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04247860)
17787a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01a3eaec)
17797a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01a3eaf8)
17807a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x541e304f)  // remoting_core!sftk_SessionFromHandle+0x58
17817a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x0404c620)
17827a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17837a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01a3eb2c)
17847a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01a3ec08)
17857a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000014)
17867a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_ebp)
17877a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(frame2_ebp)  // Child %ebp
17887a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x541e1234)  // return address of frame 1
17897a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                      // inside remoting_core!NSC_Verify+0x61
17907a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame2_esp)
17917a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04247858)
17927a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x0404c620)
17937a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
17947a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01a3ec08)
17957a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000014)
17967a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01000005)
17977a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00b2f7a0)
17987a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x041f0420)
17997a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x041f3650)
18007a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame2_ebp)
18017a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(frame3_ebp)  // Child %ebp
18027a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x541b734d)  // return address of frame 1
18037a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                      // inside remoting_core!PK11_Verify+0x139
18047a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame3_esp)
18057a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01000005)
18067a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x01a3ec08)
18077a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000014)
18087a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x0404c620)
18097a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000040)
18107a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04073e00)
18117a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04073e00)
18127a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x04247050)
18137a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00001041)
18147a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
18157a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
18167a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x00000000)
18177a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame3_ebp)
18187a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0)           // saved %ebp (stack end)
18197a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0);          // saved %eip (stack end)
18207a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18217a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  RegionFromSection();
18227a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.eip = 0x4247860;   // IP address not in known module
18237a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebp = 0x5420362d;  // bogus
18247a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.esp = frame0_esp.Value();
18257a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18267a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  // sanity
18277a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
18287a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18297a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
18307a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
18317a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com                        &local_modules, &frame_symbolizer);
18327a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  vector<const CodeModule*> modules_without_symbols;
18332d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  vector<const CodeModule*> modules_with_corrupt_symbols;
18342d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
18352d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                          &modules_with_corrupt_symbols));
18367a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  ASSERT_EQ(0U, modules_without_symbols.size());
18372d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (has_corrupt_symbols) {
18382d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    ASSERT_EQ(1U, modules_with_corrupt_symbols.size());
18392d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    ASSERT_EQ("remoting_core.dll",
18402d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com              modules_with_corrupt_symbols[0]->debug_file());
18412d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  } else {
18422d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
18432d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  }
18447a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  frames = call_stack.frames();
18457a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18467a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  ASSERT_EQ(4U, frames->size());
18477a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18487a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
18497a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
18507a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
18517a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
18527a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(raw_context.eip, frame0->context.eip);
18537a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(raw_context.ebp, frame0->context.ebp);
18547a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(raw_context.esp, frame0->context.esp);
18557a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(NULL, frame0->module);  // IP not in known module
18567a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("", frame0->function_name);
18577a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_EQ(NULL, frame0->windows_frame_info);
18587a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  }
18597a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18607a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
18617a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
18627a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
18637a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
18647a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
18657a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
18667a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame1->context_validity);
18677a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
18687a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
18697a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(&remoting_core_dll, frame1->module);
18707a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("nsc_ECDSAVerifyStub", frame1->function_name);
18717a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_TRUE(frame1->windows_frame_info != NULL);
18727a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
18737a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
18747a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame1->windows_frame_info->type_);
18757a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
18767a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame1->windows_frame_info->program_string);
18777a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
18787a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  }
18797a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
18807a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
18817a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
18827a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
18837a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
18847a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
18857a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
18867a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame2->context_validity);
18877a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
18887a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
18897a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(&remoting_core_dll, frame2->module);
18907a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("NSC_Verify", frame2->function_name);
18917a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_TRUE(frame2->windows_frame_info != NULL);
18927a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
18937a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
18947a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame2->windows_frame_info->type_);
18957a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
18967a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame2->windows_frame_info->program_string);
18977a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
18987a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  }
18997a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
19007a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  {  // To avoid reusing locals by mistake
19017a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    StackFrameX86 *frame3 = static_cast<StackFrameX86 *>(frames->at(3));
19027a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame3->trust);
19037a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
19047a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_ESP |
19057a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com               StackFrameX86::CONTEXT_VALID_EBP),
19067a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame3->context_validity);
19077a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame3_ebp.Value(), frame3->context.ebp);
19087a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(frame3_esp.Value(), frame3->context.esp);
19097a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(&remoting_core_dll, frame3->module);
19107a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("PK11_Verify", frame3->function_name);
19117a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    ASSERT_TRUE(frame3->windows_frame_info != NULL);
19127a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame3->windows_frame_info->valid);
19137a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
19147a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame3->windows_frame_info->type_);
19157a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
19167a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com              frame3->windows_frame_info->program_string);
19177a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    EXPECT_FALSE(frame3->windows_frame_info->allocates_base_pointer);
19187a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  }
19197a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com}
19207a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com
19212d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com// Runs IPAddressIsNotInKnownModule test with good symbols
19222d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.comTEST_F(GetCallerFrame, IPAddressIsNotInKnownModule) {
19232d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  IPAddressIsNotInKnownModuleTestImpl(false /* has_corrupt_modules */);
19242d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com}
19252d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com
19262d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com// Runs IPAddressIsNotInKnownModule test with corrupt symbols
19272d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.comTEST_F(GetCallerFrame, IPAddressIsNotInKnownModule_CorruptSymbols) {
19282d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  IPAddressIsNotInKnownModuleTestImpl(true /* has_corrupt_modules */);
19292d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com}
19302d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com
19316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandystruct CFIFixture: public StackwalkerX86Fixture {
19326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CFIFixture() {
19336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // Provide a bunch of STACK CFI records; individual tests walk to the
19346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // caller from every point in this series, expecting to find the same
19356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // set of register values.
19366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    SetModuleSymbols(&module1,
19376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // The youngest frame's function.
19386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "FUNC 4000 1000 10 enchiridion\n"
19396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Initially, just a return address.
19406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n"
19416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Push %ebx.
19426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n"
19436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Move %esi into %ebx.  Weird, but permitted.
19446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI 4002 $esi: $ebx\n"
19456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Allocate frame space, and save %edi.
19466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n"
19476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Put the return address in %edi.
19486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI 4005 .ra: $edi\n"
19496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Save %ebp, and use it as a frame pointer.
19506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n"
19516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
19526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // The calling function.
19536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "FUNC 5000 1000 10 epictetus\n"
19546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     // Mark it as end of stack.
19556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy                     "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n");
19566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
19576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // Provide some distinctive values for the caller's registers.
19586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    expected.esp = 0x80000000;
19596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    expected.eip = 0x40005510;
19606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    expected.ebp = 0xc0d4aab9;
19616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    expected.ebx = 0x60f20ce6;
19626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    expected.esi = 0x53d1379d;
19636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    expected.edi = 0xafbae234;
19646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
19656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    // By default, registers are unchanged.
19666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    raw_context = expected;
19676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  }
19686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
19696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // Walk the stack, using stack_section as the contents of the stack
19706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // and raw_context as the current register values. (Set
19716d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // raw_context.esp to the stack's starting address.) Expect two
19726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // stack frames; in the older frame, expect the callee-saves
19736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // registers to have values matching those in 'expected'.
19746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  void CheckWalk() {
19756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    RegionFromSection();
19766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    raw_context.esp = stack_section.start().Value();
19776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
19789753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
19796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
19809753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com                          &frame_symbolizer);
19815a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com    vector<const CodeModule*> modules_without_symbols;
19822d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    vector<const CodeModule*> modules_with_corrupt_symbols;
19832d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
19842d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                            &modules_with_corrupt_symbols));
19855a2106b5f95f3232ac0e9aab5f081eb04313a8b6ivan.penkov@gmail.com    ASSERT_EQ(0U, modules_without_symbols.size());
19862d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
19876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    frames = call_stack.frames();
19886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy    ASSERT_EQ(2U, frames->size());
19896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
19902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    {  // To avoid reusing locals by mistake
19912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
19922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
19932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
19942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ("enchiridion", frame0->function_name);
19952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(0x40004000U, frame0->function_base);
19962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      ASSERT_TRUE(frame0->windows_frame_info != NULL);
19972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
19982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                frame0->windows_frame_info->valid);
19992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      ASSERT_TRUE(frame0->cfi_frame_info != NULL);
20002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    }
20012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com
20022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    {  // To avoid reusing locals by mistake
20032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
20042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
20052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
20062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                 StackFrameX86::CONTEXT_VALID_ESP |
20072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                 StackFrameX86::CONTEXT_VALID_EBP |
20082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                 StackFrameX86::CONTEXT_VALID_EBX |
20092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                 StackFrameX86::CONTEXT_VALID_ESI |
20102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                 StackFrameX86::CONTEXT_VALID_EDI),
20112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com                 frame1->context_validity);
20122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(expected.eip, frame1->context.eip);
20132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(expected.esp, frame1->context.esp);
20142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(expected.ebp, frame1->context.ebp);
20152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(expected.ebx, frame1->context.ebx);
20162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(expected.esi, frame1->context.esi);
20172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ(expected.edi, frame1->context.edi);
20182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com      EXPECT_EQ("epictetus", frame1->function_name);
20192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com    }
20206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  }
20216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  // The values the stack walker should find for the caller's registers.
20236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  MDRawContextX86 expected;
20246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy};
20256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass CFI: public CFIFixture, public Test { };
20276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4000) {
20296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
20306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
20317a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x40005510)             // return address
20327a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
20336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004000;
20346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
20356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
20366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4001) {
20386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
20396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
20407a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x60f20ce6)             // saved %ebx
20417a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x40005510)             // return address
20427a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
20436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004001;
20447a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebx = 0x91aa9a8b;  // callee's %ebx value
20456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
20466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
20476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4002) {
20496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
20506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
20517a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x60f20ce6)             // saved %ebx
20527a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x40005510)             // return address
20537a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
20546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004002;
20557a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebx = 0x53d1379d;  // saved %esi
20567a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.esi = 0xa5c790ed;  // callee's %esi value
20576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
20586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
20596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4003) {
20616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
20626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
20637a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x56ec3db7)             // garbage
20647a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xafbae234)             // saved %edi
20657a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x53d67131)             // garbage
20667a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x60f20ce6)             // saved %ebx
20677a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x40005510)             // return address
20687a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
20696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004003;
20707a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebx = 0x53d1379d;  // saved %esi
20717a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.esi = 0xa97f229d;  // callee's %esi
20727a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.edi = 0xb05cc997;  // callee's %edi
20736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
20746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
20756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// The results here should be the same as those at module offset
20776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 0x4003.
20786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4004) {
20796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
20806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
20817a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xe29782c2)             // garbage
20827a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xafbae234)             // saved %edi
20837a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x5ba29ce9)             // garbage
20847a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x60f20ce6)             // saved %ebx
20857a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x40005510)             // return address
20867a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
20876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004004;
20887a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebx = 0x53d1379d;  // saved %esi
20897a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.esi = 0x0fb7dc4e;  // callee's %esi
20907a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.edi = 0x993b4280;  // callee's %edi
20916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
20926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
20936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
20946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4005) {
20956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
20966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
20977a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xe29782c2)             // garbage
20987a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xafbae234)             // saved %edi
20997a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x5ba29ce9)             // garbage
21007a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x60f20ce6)             // saved %ebx
21017a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x8036cc02)             // garbage
21027a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
21036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004005;
21047a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebx = 0x53d1379d;  // saved %esi
21057a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.esi = 0x0fb7dc4e;  // callee's %esi
21067a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.edi = 0x40005510;  // return address
21076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
21086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
21096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
21106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4006) {
21116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame0_ebp;
21126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  Label frame1_esp = expected.esp;
21136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  stack_section
21147a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xdcdd25cd)             // garbage
21157a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xafbae234)             // saved %edi
21167a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0xc0d4aab9)             // saved %ebp
21177a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame0_ebp)           // frame pointer points here
21187a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x60f20ce6)             // saved %ebx
21197a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .D32(0x8036cc02)             // garbage
21207a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com    .Mark(&frame1_esp);          // This effectively sets stack_section.start().
21216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.eip = 0x40004006;
21226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  raw_context.ebp = frame0_ebp.Value();
21237a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.ebx = 0x53d1379d;  // saved %esi
21247a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.esi = 0x743833c9;  // callee's %esi
21257a58af62ecb1e3d76ea0c0d0ad6198e378b4e3f4ivan.penkov@gmail.com  raw_context.edi = 0x40005510;  // return address
21266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy  CheckWalk();
21276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}
21286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy
2129