stackwalker_x86_unittest.cc revision 3108b9dd7bbac28dd01d78f9264fe494ee9c95a0
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" 43a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/processor/source_line_resolver_interface.h" 44a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "google_breakpad/processor/stack_frame_cpu.h" 45a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "processor/stackwalker_unittest_utils.h" 46a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "processor/stackwalker_x86.h" 47a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy#include "processor/windows_frame_info.h" 48a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 49a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::BasicSourceLineResolver; 50a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::CallStack; 519753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.comusing google_breakpad::StackFrameSymbolizer; 52a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::StackFrame; 53a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::StackFrameX86; 54a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::StackwalkerX86; 55a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::SystemInfo; 56a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing google_breakpad::WindowsFrameInfo; 576f598cc435f8c557b33f85802f1571ef745c37b0ted.mielczarekusing google_breakpad::test_assembler::kLittleEndian; 586f598cc435f8c557b33f85802f1571ef745c37b0ted.mielczarekusing google_breakpad::test_assembler::Label; 596f598cc435f8c557b33f85802f1571ef745c37b0ted.mielczarekusing google_breakpad::test_assembler::Section; 60a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing std::vector; 61a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::_; 62a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::Return; 63a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::SetArgumentPointee; 64a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyusing testing::Test; 65a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 66a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyclass StackwalkerX86Fixture { 67a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy public: 68a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86Fixture() 69a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy : stack_section(kLittleEndian), 70a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Give the two modules reasonable standard locations and names 71a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // for tests to play with. 72a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy module1(0x40000000, 0x10000, "module1", "version1"), 732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com module2(0x50000000, 0x10000, "module2", "version2"), 742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com module3(0x771d0000, 0x180000, "module3", "version3"), 752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com module4(0x75f90000, 0x46000, "module4", "version4"), 762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com module5(0x75730000, 0x110000, "module5", "version5"), 772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com module6(0x647f0000, 0x1ba8000, "module6", "version6") { 78a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Identify the system as a Linux system. 79a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy system_info.os = "Linux"; 80a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy system_info.os_short = "linux"; 81a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy system_info.os_version = "Salacious Skink"; 82a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy system_info.cpu = "x86"; 83a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy system_info.cpu_info = ""; 84a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 85a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Put distinctive values in the raw CPU context. 86a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy BrandContext(&raw_context); 87a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 88a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Create some modules with some stock debugging information. 89a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy modules.Add(&module1); 90a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy modules.Add(&module2); 912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com modules.Add(&module3); 922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com modules.Add(&module4); 932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com modules.Add(&module5); 942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com modules.Add(&module6); 95a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 96a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // By default, none of the modules have symbol info; call 97a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // SetModuleSymbols to override this. 985b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _)) 99a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); 100a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy } 101a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 102a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Set the Breakpad symbol information that supplier should return for 103a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // MODULE to INFO. 104a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy void SetModuleSymbols(MockCodeModule *module, const string &info) { 105df823ad6d7ec7b82d256ccfae2df859f9cb6060bivan.penkov@gmail.com char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info); 1065b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _)) 1075b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), 108a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Return(MockSymbolSupplier::FOUND))); 109a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy } 110a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 111a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Populate stack_region with the contents of stack_section. Use 112a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // stack_section.start() as the region's starting address. 113a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy void RegionFromSection() { 114a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy string contents; 115a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(stack_section.GetContents(&contents)); 116a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_region.Init(stack_section.start().Value(), contents); 117a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy } 118a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 119a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. 120a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy void BrandContext(MDRawContextX86 *raw_context) { 121a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy u_int8_t x = 173; 122a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy for (size_t i = 0; i < sizeof(*raw_context); i++) 123a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy reinterpret_cast<u_int8_t *>(raw_context)[i] = (x += 17); 124a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy } 125a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 126a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SystemInfo system_info; 127a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy MDRawContextX86 raw_context; 128a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Section stack_section; 129a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy MockMemoryRegion stack_region; 130a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy MockCodeModule module1; 131a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy MockCodeModule module2; 1322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com MockCodeModule module3; 1332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com MockCodeModule module4; 1342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com MockCodeModule module5; 1352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com MockCodeModule module6; 136a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy MockCodeModules modules; 137a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy MockSymbolSupplier supplier; 138a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy BasicSourceLineResolver resolver; 139a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy CallStack call_stack; 140a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy const vector<StackFrame *> *frames; 141a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy}; 142a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 143281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarekclass SanityCheck: public StackwalkerX86Fixture, public Test { }; 144281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek 145281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarekTEST_F(SanityCheck, NoResolver) { 146281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek stack_section.start() = 0x80000000; 147281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek stack_section.D32(0).D32(0); // end-of-stack marker 148281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek RegionFromSection(); 149281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek raw_context.eip = 0x40000200; 150281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek raw_context.ebp = 0x80000000; 151281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek 1529753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(NULL, NULL); 153281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1549753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 155281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek // This should succeed, even without a resolver or supplier. 156281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek ASSERT_TRUE(walker.Walk(&call_stack)); 157281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek frames = call_stack.frames(); 158281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); 159281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek // Check that the values from the original raw context made it 160281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek // through to the context in the stack frame. 161281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 162281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek} 163281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek 164a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyclass GetContextFrame: public StackwalkerX86Fixture, public Test { }; 165a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 166a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetContextFrame, Simple) { 167a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 168a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.D32(0).D32(0); // end-of-stack marker 169a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 170a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x40000200; 171a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = 0x80000000; 172a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 1739753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 174a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1759753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 176a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 177a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 178a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); 179a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Check that the values from the original raw context made it 180a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // through to the context in the stack frame. 181281d52d944d63ddfbe933a7bbe8adbfba3523966ted.mielczarek EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 182a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 183a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 184a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyclass GetCallerFrame: public StackwalkerX86Fixture, public Test { }; 185a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 186a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Walk a traditional frame. A traditional frame saves the caller's 187a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// %ebp just below the return address, and has its own %ebp pointing 188a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// at the saved %ebp. 189a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, Traditional) { 190a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 191a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame0_ebp, frame1_ebp; 192a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 193a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(12, 0) // frame 0: space 194a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame0_ebp) // frame 0 %ebp points here 195a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(frame1_ebp) // frame 0: saved %ebp 196a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x40008679) // frame 0: return address 197a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(8, 0) // frame 1: space 198a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_ebp) // frame 1 %ebp points here 199a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0) // frame 1: saved %ebp (stack end) 200a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0); // frame 1: return address (stack end) 201a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 202a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x4000c7a5; 203a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 204a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = frame0_ebp.Value(); 205a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 2069753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 207a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 2089753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 209a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 210a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 211a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 212a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 2132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 2142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 2152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 2162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 2172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000c7a5U, frame0->instruction); 2182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000c7a5U, frame0->context.eip); 2192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 2202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame0->windows_frame_info); 2212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 2222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 2232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 2242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 2252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 2262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 2272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 2282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 2292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 2302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40008679U, frame1->instruction + 1); 2312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40008679U, frame1->context.eip); 2322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 2332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 2342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 235a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 236a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 237a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Walk a traditional frame, but use a bogus %ebp value, forcing a scan 238a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// of the stack for something that looks like a return address. 239a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, TraditionalScan) { 240a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 241a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame1_ebp; 242a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 243a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0 244a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xf065dc76) // locals area: 245a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x46ee2167) // garbage that doesn't look like 246a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xbab023ec) // a return address 247a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) 248a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x4000129d) // return address 249a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1 250a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(8, 0) // space 251a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_ebp) // %ebp points here 252a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0) // saved %ebp (stack end) 253a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0); // return address (stack end) 254a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 255a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 256a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x4000f49d; 257a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 258a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Make the frame pointer bogus, to make the stackwalker scan the stack 259a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // for something that looks like a return address. 260a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = 0xd43eed6e; 261a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 2629753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 263a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 2649753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 265a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 266a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 267a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 268a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 2692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 2702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 2712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 2722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 2732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000f49dU, frame0->instruction); 2742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000f49dU, frame0->context.eip); 2752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 2762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xd43eed6eU, 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_SCAN, frame1->trust); 2832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 2842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // walker does not actually fetch the EBP after a scan (forcing the 2852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // next frame to be scanned as well). But let's grandfather the existing 2862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // behavior in for now. 2872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 2882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 2892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 2902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 2912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000129dU, frame1->instruction + 1); 2922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000129dU, frame1->context.eip); 2932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x80000014U, frame1->context.esp); 2942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xd43eed6eU, frame1->context.ebp); 2952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 2962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 297a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 298a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 2999c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek// Force scanning for a return address a long way down the stack 3009c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarekTEST_F(GetCallerFrame, TraditionalScanLongWay) { 3019c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek stack_section.start() = 0x80000000; 3029c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek Label frame1_ebp; 3039c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek stack_section 3049c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek // frame 0 3059c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(0xf065dc76) // locals area: 3069c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(0x46ee2167) // garbage that doesn't look like 3079c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(0xbab023ec) // a return address 3089c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .Append(20 * 4, 0) // a bunch of space 3099c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) 3109c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(0x4000129d) // return address 3119c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek // frame 1 3129c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .Append(8, 0) // space 3139c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .Mark(&frame1_ebp) // %ebp points here 3149c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(0) // saved %ebp (stack end) 3159c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek .D32(0); // return address (stack end) 3169c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek 3179c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek RegionFromSection(); 3189c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek raw_context.eip = 0x4000f49d; 3199c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek raw_context.esp = stack_section.start().Value(); 3209c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek // Make the frame pointer bogus, to make the stackwalker scan the stack 3219c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek // for something that looks like a return address. 3229c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek raw_context.ebp = 0xd43eed6e; 3239c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek 3249753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 3259c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 3269753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 3279c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek ASSERT_TRUE(walker.Walk(&call_stack)); 3289c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek frames = call_stack.frames(); 3299c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek ASSERT_EQ(2U, frames->size()); 3309c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek 3312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 3322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 3332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 3342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 3352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000f49dU, frame0->instruction); 3362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000f49dU, frame0->context.eip); 3372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 3382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); 3392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame0->windows_frame_info); 3402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 3412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 3422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 3432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 3442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 3452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 3462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // walker does not actually fetch the EBP after a scan (forcing the 3472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // next frame to be scanned as well). But let's grandfather the existing 3482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // behavior in for now. 3492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 3502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 3512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 3522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 3532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000129dU, frame1->instruction + 1); 3542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000129dU, frame1->context.eip); 3552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x80000064U, frame1->context.esp); 3562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xd43eed6eU, frame1->context.ebp); 3572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 3582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 3599c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek} 3609c30407f7f2c6e6a352cd62fe4be21fe55ee1879ted.mielczarek 361a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a 362a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a stack frame. 363a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameData) { 364a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module1, 365a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" 366a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $T2 $esp .cbSavedRegs + =" 367a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $T0 .raSearchStart =" 368a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $eip $T0 ^ =" 369a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $esp $T0 4 + =" 370a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $ebx $T2 4 - ^ =" 371a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $edi $T2 8 - ^ =" 372a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $esi $T2 12 - ^ =" 373a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $ebp $T2 16 - ^ =\n"); 374a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame1_esp, frame1_ebp; 375a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 376a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 377a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0 378a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(frame1_ebp) // saved regs: %ebp 379a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xa7120d1a) // %esi 380a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x630891be) // %edi 381a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x9068a878) // %ebx 382a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xa08ea45f) // locals: unused 383a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x40001350) // return address 384a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1 385a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_esp) 386a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(12, 0) // empty space 387a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_ebp) 388a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0) // saved %ebp (stack end) 389a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0); // saved %eip (stack end) 390a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 391a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 392a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x4000aa85; 393a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 394a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = 0xf052c1de; // should not be needed to walk frame 395a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 3969753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 397a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 3989753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 399a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 400a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 401a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 402a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 4032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 4042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 4052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 4062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 4072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000aa85U, frame0->instruction); 4082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000aa85U, frame0->context.eip); 4092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 4102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xf052c1deU, frame0->context.ebp); 4112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame0->windows_frame_info != NULL); 4122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 4132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 4142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 4152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 4162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 4172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 4182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 4192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP 4202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBX 4212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESI 4222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EDI), 4232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 4242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40001350U, frame1->instruction + 1); 4252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40001350U, frame1->context.eip); 4262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 4272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 4282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x9068a878U, frame1->context.ebx); 4292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xa7120d1aU, frame1->context.esi); 4302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x630891beU, frame1->context.edi); 4312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 4322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 433a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 434a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 435a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a 4366679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org// FrameTypeFrameData DIA record) to walk a stack frame where the stack 4376679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org// is aligned and we must search 4386679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.orgTEST_F(GetCallerFrame, WindowsFrameDataAligned) { 4396679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org SetModuleSymbols(&module1, 4406679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org "STACK WIN 4 aa85 176 0 0 4 4 8 0 1" 4416679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org " $T1 .raSearch =" 4426679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org " $T0 $T1 4 - 8 @ =" 4436679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org " $ebp $T1 4 - ^ =" 4446679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org " $eip $T1 ^ =" 4456679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org " $esp $T1 4 + ="); 4466679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org Label frame1_esp, frame1_ebp; 4476679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org stack_section.start() = 0x80000000; 4486679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org stack_section 4496679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org // frame 0 4506679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0x0ffa0ffa) // unused saved register 4516679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0xdeaddead) // locals 4526679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0xbeefbeef) 4536679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0) // 8-byte alignment 4546679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(frame1_ebp) 4556679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0x5000129d) // return address 4566679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org // frame 1 4576679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .Mark(&frame1_esp) 4586679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0x1) // parameter 4596679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .Mark(&frame1_ebp) 4606679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0) // saved %ebp (stack end) 4616679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org .D32(0); // saved %eip (stack end) 4626679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org 4636679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org RegionFromSection(); 4646679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org raw_context.eip = 0x4000aa85; 4656679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org raw_context.esp = stack_section.start().Value(); 4666679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org raw_context.ebp = 0xf052c1de; // should not be needed to walk frame 4676679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org 4689753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 4696679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 4709753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 4716679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org ASSERT_TRUE(walker.Walk(&call_stack)); 4726679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org frames = call_stack.frames(); 4736679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org ASSERT_EQ(2U, frames->size()); 4746679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org 4752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 4762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 4772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 4782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 4792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000aa85U, frame0->instruction); 4802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000aa85U, frame0->context.eip); 4812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 4822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xf052c1deU, frame0->context.ebp); 4832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame0->windows_frame_info != NULL); 4842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 4852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 4862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 4872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 4882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 4892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 4902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 4912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 4922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 4932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000129dU, frame1->instruction + 1); 4942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000129dU, frame1->context.eip); 4952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 4962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 4972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 4982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 4996679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org} 5006679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org 5016679ad568c3e3796acab4022dbfdcfad484e34e8mark@chromium.org// Use Windows frame data (a "STACK WIN 4" record, from a 502a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a frame, and depend on the 503a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// parameter size from the callee as well. 504a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { 505a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n"); 506a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module2, 5076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Note bogus parameter size in FUNC record; the stack walker 5086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // should prefer the STACK WIN record, and see '4' below. 509a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "FUNC aa85 176 beef module2::whine\n" 510a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" 511a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $T2 $esp .cbLocals + .cbSavedRegs + =" 512a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $T0 .raSearchStart =" 513a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $eip $T0 ^ =" 514a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $esp $T0 4 + =" 515a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $ebp $T0 20 - ^ =" 516a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $ebx $T0 8 - ^ =\n"); 517a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame0_esp, frame0_ebp; 518a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame1_esp; 519a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame2_esp, frame2_ebp; 520a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 521a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 522a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0, in module1::wheedle. Traditional frame. 523a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame0_esp) 524a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(16, 0) // frame space 525a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame0_ebp) 526a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x6fa902e0) // saved %ebp. Not a frame pointer. 527a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x5000aa95) // return address, in module2::whine 528a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1, in module2::whine. FrameData frame. 529a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_esp) 530a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle 531a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xbdc92f9f) // argument 2 532a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x0b1d8442) // argument 1 533a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(frame2_ebp) // saved %ebp 534a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xb1b90a15) // unused 535a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xf18e072d) // unused 536a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x2558c7f3) // saved %ebx 537a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x0365e25e) // unused 538a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x2a179e38) // return address; $T0 points here 539a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 2, in no module 540a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame2_esp) 541a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(12, 0) // empty space 542a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame2_ebp) 543a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0) // saved %ebp (stack end) 544a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0); // saved %eip (stack end) 545a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 546a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 547a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x40001004; // in module1::wheedle 548a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 549a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = frame0_ebp.Value(); 550a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 5519753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 552a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 5539753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 554a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 555a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 556a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(3U, frames->size()); 557a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 5582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 5592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 5602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 5612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 5622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40001004U, frame0->instruction); 5632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40001004U, frame0->context.eip); 5642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 5652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 5662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module1, frame0->module); 5672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("module1::wheedle", frame0->function_name); 5682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40001000U, frame0->function_base); 5692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // The FUNC record for module1::wheedle should have produced a 5702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // WindowsFrameInfo structure with only the parameter size valid. 5712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame0->windows_frame_info != NULL); 5722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, 5732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame0->windows_frame_info->valid); 5742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN, 5752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame0->windows_frame_info->type_); 5762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size); 5772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 5782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 5792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 5802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 5812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 5822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 5832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 5842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 5852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 5862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000aa95U, frame1->instruction + 1); 5872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000aa95U, frame1->context.eip); 5882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 5892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x6fa902e0U, frame1->context.ebp); 5902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module2, frame1->module); 5912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("module2::whine", frame1->function_name); 5922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000aa85U, frame1->function_base); 5932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame1->windows_frame_info != NULL); 5942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 5952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 5962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->windows_frame_info->type_); 5972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // This should not see the 0xbeef parameter size from the FUNC 5982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // record, but should instead see the STACK WIN record. 5992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size); 6002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 6012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 6022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 6032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); 6042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 6052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 6062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 6072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP 6082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBX), 6092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame2->context_validity); 6102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x2a179e38U, frame2->instruction + 1); 6112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x2a179e38U, frame2->context.eip); 6122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); 6132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp); 6142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x2558c7f3U, frame2->context.ebx); 6152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame2->module); 6162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame2->windows_frame_info); 6172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 618a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 619a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 620a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a 621a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a stack frame, where the 6226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// expression fails to yield both an $eip and an $ebp value, and the stack 6236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// walker must scan. 624a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameDataScan) { 625a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module1, 626a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n"); 627a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Mark frame 1's PC as the end of the stack. 628a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module2, 629a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "FUNC 7c38 accf 0 module2::function\n" 630a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n"); 631a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame1_esp; 632a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 633a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 634a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0 635a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(16, 0x2a) // unused, garbage 636a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x50007ce9) // return address 637a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1 638a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_esp) 639a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(8, 0); // empty space 640a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 641a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 642a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x40000c9c; 643a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 644a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame 645a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 6469753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 647a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 6489753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 649a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 650a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 651a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 652a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 6532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 6542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 6552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 6562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 6572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40000c9cU, frame0->instruction); 6582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40000c9cU, frame0->context.eip); 6592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 6602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x2ae314cdU, frame0->context.ebp); 6612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame0->windows_frame_info != NULL); 6622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 6632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 6642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 6652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 6662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 6672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker 6682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // does not actually fetch the EBP after a scan (forcing the next frame 6692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // to be scanned as well). But let's grandfather the existing behavior in 6702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // for now. 6712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 6722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 6732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 6742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 6752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x50007ce9U, frame1->instruction + 1); 6762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x50007ce9U, frame1->context.eip); 6772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 6782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame1->windows_frame_info != NULL); 6792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 680a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 681a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 682a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows frame data (a "STACK WIN 4" record, from a 683a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// FrameTypeFrameData DIA record) to walk a stack frame, where the 6846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// expression yields an $eip that falls outside of any module, and the 6856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// stack walker must scan. 686a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { 687a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module1, 688a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1" 689a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // A traditional frame, actually. 690a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n"); 691a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Mark frame 1's PC as the end of the stack. 692a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module2, 693a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "FUNC cfdb 8406 0 module2::function\n" 694a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n"); 695a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 696a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 697a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // In this stack, the context's %ebp is pointing at the wrong place, so 6986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // the stack walker needs to scan to find the return address, and then 6996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // scan again to find the caller's saved %ebp. 700a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame0_ebp, frame1_ebp, frame1_esp; 701a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 702a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0 703a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(8, 0x2a) // garbage 704a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point 705a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // at *** below 706a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // The STACK WIN record says that the following two values are 707a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1's saved %ebp and return address, but the %ebp is wrong; 7086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // they're garbage. The stack walker will scan for the right values. 709a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp 710a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x17847f5b) // alleged to be frame 1's return address 711a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find 712a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x2b2b2b2b) // first word of realigned register save area 713a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // *** frame 0 %ebp ought to be pointing here 714a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x2c2c2c2c) // realigned locals area 715a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x5000d000) // frame 1's real saved %eip; scan will find 716a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Frame 1, in module2::function. The STACK WIN record describes 717a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // this as the oldest frame, without referring to its contents, so 7186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // we needn't to provide any actual data here. 719a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_esp) 720a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_ebp) // frame 1 %ebp points here 721a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // A dummy value for frame 1's %ebp to point at. The scan recognizes the 722a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // saved %ebp because it points to a valid word in the stack memory region. 723a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x2d2d2d2d); 724a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 725a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 726a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x40000700; 727a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 728a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = frame0_ebp.Value(); 729a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 7309753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 731a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 7329753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 733a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 734a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 735a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 736a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 7372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 7382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 7392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 7402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 7412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40000700U, frame0->instruction); 7422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40000700U, frame0->context.eip); 7432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 7442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 7452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame0->windows_frame_info != NULL); 7462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 7472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 7482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 7492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 7502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); 7512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 7522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // walker does not actually fetch the EBP after a scan (forcing the 7532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // next frame to be scanned as well). But let's grandfather the existing 7542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // behavior in for now. 7552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 7562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 7572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 7582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 7592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000d000U, frame1->instruction + 1); 7602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x5000d000U, frame1->context.eip); 7612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 7622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 7632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame1->windows_frame_info != NULL); 7642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 765a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 766a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 767a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows FrameTypeFPO data to walk a stack frame for a function that 768a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// does not modify %ebp from the value it had in the caller. 769a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { 770a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module1, 7716d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Note bogus parameter size in FUNC record; the walker 7726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // should prefer the STACK WIN record, and see the '8' below. 773a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "FUNC e8a8 100 feeb module1::discombobulated\n" 774a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n"); 775a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame0_esp; 776a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame1_esp, frame1_ebp; 777a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 778a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 779a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. 780a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame0_esp) 781a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // no outgoing parameters; this is the youngest frame. 782a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x7c521352) // four bytes of saved registers 783a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Append(0x10, 0x42) // local area 784a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x40009b5b) // return address, in module1, no function 785a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1, in module1, no function. 786a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_esp) 787a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xf60ea7fc) // junk 788a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_ebp) 789a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0) // saved %ebp (stack end) 790a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0); // saved %eip (stack end) 791a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 792a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 793a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x4000e8b8; // in module1::whine 794a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 795a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // Frame pointer unchanged from caller. 796a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = frame1_ebp.Value(); 797a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 7989753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 799a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 8009753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 801a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 802a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 803a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 804a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 8052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 8062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 8072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 8082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 8092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000e8b8U, frame0->instruction); 8102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000e8b8U, frame0->context.eip); 8112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 8122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); // unchanged from caller 8132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module1, frame0->module); 8142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("module1::discombobulated", frame0->function_name); 8152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000e8a8U, frame0->function_base); 8162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // The STACK WIN record for module1::discombobulated should have 8172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // produced a fully populated WindowsFrameInfo structure. 8182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame0->windows_frame_info != NULL); 8192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 8202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 8212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame0->windows_frame_info->type_); 8222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size); 8232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 8242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 8252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 8262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 8272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 8282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 8292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 8302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 8312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 8322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40009b5bU, frame1->instruction + 1); 8332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40009b5bU, frame1->context.eip); 8342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 8352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 8362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module1, frame1->module); 8372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("", frame1->function_name); 8382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 8392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 840a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 841a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 842a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// Use Windows FrameTypeFPO data to walk a stack frame for a function 843a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// that uses %ebp for its own purposes, saving the value it had in the 844a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy// caller in the standard place in the saved register area. 845a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandyTEST_F(GetCallerFrame, WindowsFPOUsedEBP) { 846a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy SetModuleSymbols(&module1, 8476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Note bogus parameter size in FUNC record; the walker 8486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // should prefer the STACK WIN record, and see the '8' below. 849a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n" 850a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n"); 851a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame0_esp; 852a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy Label frame1_esp, frame1_ebp; 853a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section.start() = 0x80000000; 854a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy stack_section 855a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. 856a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame0_esp) 857a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // no outgoing parameters; this is the youngest frame. 858a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(frame1_ebp) // saved register area: saved %ebp 859a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xb68bd5f9) // saved register area: something else 860a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xd25d05fc) // local area 861a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0x4000debe) // return address, in module1, no function 862a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // frame 1, in module1, no function. 863a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_esp) 864a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0xf0c9a974) // junk 865a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .Mark(&frame1_ebp) 866a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0) // saved %ebp (stack end) 867a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy .D32(0); // saved %eip (stack end) 868a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 869a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy RegionFromSection(); 870a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens 871a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.esp = stack_section.start().Value(); 872a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy // RaisedByTheAliens uses %ebp for its own mysterious purposes. 873a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy raw_context.ebp = 0xecbdd1a5; 874a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 8759753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 876a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 8779753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 878a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 879a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy frames = call_stack.frames(); 880a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy ASSERT_EQ(2U, frames->size()); 881a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy 8822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 8832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 8842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 8852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 8862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40009ab8U, frame0->instruction); 8872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40009ab8U, frame0->context.eip); 8882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 8892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0xecbdd1a5, frame0->context.ebp); 8902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module1, frame0->module); 8912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name); 8922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40009aa8U, frame0->function_base); 8932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // The STACK WIN record for module1::RaisedByTheAliens should have 8942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // produced a fully populated WindowsFrameInfo structure. 8952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame0->windows_frame_info != NULL); 8962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 8972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 8982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame0->windows_frame_info->type_); 8992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("", frame0->windows_frame_info->program_string); 9002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer); 9012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 9022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 9032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 9042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 9052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 9062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 9072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 9082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 9092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 9102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000debeU, frame1->instruction + 1); 9112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x4000debeU, frame1->context.eip); 9122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 9132660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 9142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module1, frame1->module); 9152660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("", frame1->function_name); 9162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(NULL, frame1->windows_frame_info); 9172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 9182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com} 9192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 9202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// This is a regression unit test which covers a bug which has to do with 9212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// FPO-optimized Windows system call stubs in the context frame. There is 9222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// a more recent Windows system call dispatch mechanism which differs from 9232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// the one which is being tested here. The newer system call dispatch 9242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com// mechanism creates an extra context frame (KiFastSystemCallRet). 9252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.comTEST_F(GetCallerFrame, WindowsFPOSystemCall) { 9262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com SetModuleSymbols(&module3, // ntdll.dll 9272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "PUBLIC 1f8ac c ZwWaitForSingleObject\n" 9282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n"); 9292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com SetModuleSymbols(&module4, // kernelbase.dll 9302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "PUBLIC 109f9 c WaitForSingleObjectEx\n" 9312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "PUBLIC 36590 0 _except_handler4\n" 9322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip " 9332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 9342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" 9352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip " 9362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 " 9372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); 9382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com SetModuleSymbols(&module5, // kernel32.dll 9392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "PUBLIC 11136 8 WaitForSingleObject\n" 9402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "PUBLIC 11151 c WaitForSingleObjectExImplementation\n" 9412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip " 9422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 9432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" 9442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip " 9452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 9462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); 9472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com SetModuleSymbols(&module6, // chrome.dll 9482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "FILE 7038 some_file_name.h\n" 9492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "FILE 839776 some_file_name.cc\n" 9502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "FUNC 217fda 17 4 function_217fda\n" 9512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "217fda 4 102 839776\n" 9522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "FUNC 217ff1 a 4 function_217ff1\n" 9532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "217ff1 0 594 7038\n" 9542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "217ff1 a 596 7038\n" 9552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n"); 9562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 9572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com Label frame0_esp, frame1_esp; 9582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com Label frame1_ebp, frame2_ebp, frame3_ebp; 9592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com stack_section.start() = 0x002ff290; 9602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com stack_section 9612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .Mark(&frame0_esp) 9622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x771ef8c1) // EIP in frame 0 (system call) 9632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x75fa0a91) // return address of frame 0 9642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .Mark(&frame1_esp) 9652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x000017b0) // args to child 9662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x002ff2d8) 9682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x88014a2e) 9692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x002ff364) 9702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x000017b0) 9712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000024) 9732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000001) 9742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x9e3b9800) 9822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0xfffffff7) 9832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x002ff2a4) 9852660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x64a07ff1) // random value to be confused with a return address 9862660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x002ff8dc) 9872660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x75fc6590) // random value to be confused with a return address 9882660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0xfdd2c6ea) 9892660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9902660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .Mark(&frame1_ebp) 9912660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(frame2_ebp) // Child EBP 9922660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x75741194) // return address of frame 1 9932660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x000017b0) // args to child 9942660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x0036ee80) 9952660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 9962660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x65bc7d14) 9972660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .Mark(&frame2_ebp) 9982660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(frame3_ebp) // Child EBP 9992660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x75741148) // return address of frame 2 10002660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x000017b0) // args to child 10012660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x0036ee80) 10022660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0x00000000) 10032660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .Mark(&frame3_ebp) 10042660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0) // saved %ebp (stack end) 10052660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com .D32(0); // saved %eip (stack end) 10062660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 10072660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com RegionFromSection(); 10082660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject 10092660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com raw_context.esp = stack_section.start().Value(); 10102660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(raw_context.esp == frame0_esp.Value()); 10112660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com raw_context.ebp = frame1_ebp.Value(); 10122660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 10139753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 10142660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 10159753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 10162660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(walker.Walk(&call_stack)); 10172660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frames = call_stack.frames(); 10182660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 10192660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(4U, frames->size()); 10202660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 10212660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 10222660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 10232660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 10242660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 10252660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x771ef8c1U, frame0->instruction); 10262660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x771ef8c1U, frame0->context.eip); 10272660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 10282660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); 10292660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module3, frame0->module); 10302660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name); 10312660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // The STACK WIN record for module3!ZwWaitForSingleObject should have 10322660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // produced a fully populated WindowsFrameInfo structure. 10332660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame0->windows_frame_info != NULL); 10342660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 10352660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 10362660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame0->windows_frame_info->type_); 10372660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("", frame0->windows_frame_info->program_string); 10382660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); 10392660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 10402660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 10412660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 10422660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 10432660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 10442660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 10452660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_ESP 10462660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com | StackFrameX86::CONTEXT_VALID_EBP), 10472660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 10482660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1); 10492660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x75fa0a91U, frame1->context.eip); 10502660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 10512660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 10522660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(&module4, frame1->module); 10532660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name); 10542660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // The STACK WIN record for module4!WaitForSingleObjectEx should have 10552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com // produced a fully populated WindowsFrameInfo structure. 10562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame1->windows_frame_info != NULL); 10572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 10582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 10592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->windows_frame_info->type_); 10602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 10612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", 10622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->windows_frame_info->program_string); 10632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); 10642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 1065a7eb2329ded3a3315be997a7bc7ba64c5c759bd6jimblandy} 10666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 10673108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// Scan the stack for a better return address and potentially skip frames 10683108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// when the calculated return address is not in a known module. 10693108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// Note, that the span of this scan is somewhat arbitrarily limited to 30 10703108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// search words (pointers): 10713108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// const int kRASearchWords = 30; 10723108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// This means that frames can be skipped only when their size is relatively 10733108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com// small: smaller than kRASearchWords * sizeof(InstructionType) 10743108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.comTEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { 10753108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1"); 10763108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com SetModuleSymbols(&msvcrt_dll, // msvcrt.dll 10773108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "PUBLIC 38180 0 wcsstr\n" 10783108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 " 10793108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 10803108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "- = $P $T0 4 + .cbParams + =\n"); 10813108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 10823108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1"); 10833108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com SetModuleSymbols(&kernel32_dll, // kernel32.dll 10843108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "PUBLIC efda 8 FindNextFileW\n" 10853108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 " 10863108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 10873108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "- = $P $T0 4 + .cbParams + =\n"); 10883108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 10893108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1"); 10903108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com SetModuleSymbols(&chrome_dll, // chrome.dll 10913108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n" 10923108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "e3cff 1a 711 2505\n" 10933108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = " 10943108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " 10953108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " 10963108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "$T0 160 - ^ =\n"); 10973108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 10983108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // Create some modules with some stock debugging information. 10993108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com MockCodeModules local_modules; 11003108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com local_modules.Add(&msvcrt_dll); 11013108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com local_modules.Add(&kernel32_dll); 11023108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com local_modules.Add(&chrome_dll); 11033108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 11043108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com Label frame0_esp; 11053108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com Label frame0_ebp; 11063108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com Label frame1_ebp; 11073108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com Label frame2_ebp; 11083108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com Label frame3_ebp; 11093108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 11103108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com stack_section.start() = 0x0932f2d0; 11113108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com stack_section 11123108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .Mark(&frame0_esp) 11133108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e000) 11143108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e068) 11153108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .Mark(&frame0_ebp) 11163108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(frame1_ebp) // Child EBP 11173108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x001767a0) // return address of frame 0 11183108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // Not in known module 11193108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e0c6) 11203108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x001bb1b8) 11213108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e068) 11223108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000003) 11233108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e068) 11243108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000003) 11253108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x07578828) 11263108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e000) 11273108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11283108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x001c0010) 11293108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e0c6) 11303108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .Mark(&frame1_ebp) 11313108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(frame2_ebp) // Child EBP 11323108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x7c80f10f) // return address of frame 1 11333108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // inside kernel32!FindNextFileW 11343108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x000008f8) 11353108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11363108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11373108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11383108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f34c) 11393108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e000) 11403108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00001000) 11413108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11423108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000001) 11433108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11443108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11453108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f6a8) 11463108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11473108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f6d8) 11483108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11493108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x000000d6) 11503108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0764e000) 11513108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x7ff9a000) 11523108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f3fc) 11533108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000001) 11543108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000001) 11553108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x07578828) 11563108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0000002e) 11573108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f340) 11583108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932eef4) 11593108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932ffdc) 11603108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x7c839ad8) 11613108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x7c80f0d8) 11623108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11633108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .Mark(&frame2_ebp) 11643108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(frame3_ebp) // Child EBP 11653108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x01d13f91) // return address of frame 2 11663108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // inside chrome_dll!file_util::FileEnumerator::Next 11673108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x07578828) 11683108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f6ac) 11693108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f9c4) 11703108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f9b4) 11713108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11723108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000003) 11733108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f978) 11743108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x01094330) 11753108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11763108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000001) 11773108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x01094330) 11783108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11793108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11803108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x07f30000) 11813108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x01c3ba17) 11823108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x08bab840) 11833108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x07f31580) 11843108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11853108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000007) 11863108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f940) 11873108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0000002e) 11883108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f40c) 11893108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x01d13b53) 11903108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f958) 11913108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000001) 11923108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000007) 11933108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f940) 11943108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0000002e) 11953108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 11963108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f6ac) 11973108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x01e13ef0) 11983108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000001) 11993108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000007) 12003108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f958) 12013108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x08bab840) 12023108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f9b4) 12033108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x00000000) 12043108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f9b4) 12053108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x000000a7) 12063108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x000000a7) 12073108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x0932f998) 12083108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0x579627a2) 12093108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .Mark(&frame3_ebp) 12103108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0) // saved %ebp (stack end) 12113108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com .D32(0); // saved %eip (stack end) 12123108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 12133108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com RegionFromSection(); 12143108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr 12153108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com raw_context.esp = frame0_esp.Value(); 12163108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com raw_context.ebp = frame0_ebp.Value(); 12173108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // sanity 12183108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_TRUE(raw_context.esp == stack_section.start().Value()); 12193108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8); 12203108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 12213108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 12223108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackwalkerX86 walker(&system_info, &raw_context, &stack_region, 12233108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com &local_modules, &frame_symbolizer); 12243108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_TRUE(walker.Walk(&call_stack)); 12253108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frames = call_stack.frames(); 12263108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 12273108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_EQ(3U, frames->size()); 12283108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 12293108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com { // To avoid reusing locals by mistake 12303108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 12313108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 12323108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 12333108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(0x77c181cdU, frame0->instruction); 12343108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(0x77c181cdU, frame0->context.eip); 12353108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 12363108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 12373108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(&msvcrt_dll, frame0->module); 12383108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ("wcsstr", frame0->function_name); 12393108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_TRUE(frame0->windows_frame_info != NULL); 12403108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 12413108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 12423108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame0->windows_frame_info->type_); 12433108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ("$T0 $ebp = $eip $T0 " 12443108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 12453108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "- = $P $T0 4 + .cbParams + =", 12463108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame0->windows_frame_info->program_string); 12473108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // It has program string, so allocates_base_pointer is not expected 12483108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); 12493108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com } 12503108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 12513108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com { // To avoid reusing locals by mistake 12523108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 12533108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); 12543108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 12553108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_ESP | 12563108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_EBP), 12573108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame1->context_validity); 12583108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1); 12593108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(0x7c80f10fU, frame1->context.eip); 12603108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp. 12613108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp); 12623108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(&kernel32_dll, frame1->module); 12633108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ("FindNextFileW", frame1->function_name); 12643108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_TRUE(frame1->windows_frame_info != NULL); 12653108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 12663108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 12673108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame1->windows_frame_info->type_); 12683108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ("$T0 $ebp = $eip $T0 " 12693108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 12703108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "- = $P $T0 4 + .cbParams + =", 12713108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame1->windows_frame_info->program_string); 12723108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); 12733108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com } 12743108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 12753108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com { // To avoid reusing locals by mistake 12763108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); 12773108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 12783108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 12793108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_ESP | 12803108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_EBP), 12813108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame2->context_validity); 12823108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(0x01d13f91U, frame2->instruction + 1); 12833108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(0x01d13f91U, frame2->context.eip); 12843108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp. 12853108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp); 12863108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(&chrome_dll, frame2->module); 12873108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name); 12883108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com ASSERT_TRUE(frame2->windows_frame_info != NULL); 12893108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); 12903108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 12913108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame2->windows_frame_info->type_); 12923108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_EQ("$T1 .raSearch = " 12933108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " 12943108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " 12953108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com "$T0 160 - ^ =", 12963108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com frame2->windows_frame_info->program_string); 12973108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer); 12983108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com } 12993108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com} 13003108b9dd7bbac28dd01d78f9264fe494ee9c95a0ivan.penkov@gmail.com 13016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandystruct CFIFixture: public StackwalkerX86Fixture { 13026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIFixture() { 13036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Provide a bunch of STACK CFI records; individual tests walk to the 13046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // caller from every point in this series, expecting to find the same 13056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // set of register values. 13066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy SetModuleSymbols(&module1, 13076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // The youngest frame's function. 13086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "FUNC 4000 1000 10 enchiridion\n" 13096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Initially, just a return address. 13106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n" 13116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Push %ebx. 13126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n" 13136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Move %esi into %ebx. Weird, but permitted. 13146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI 4002 $esi: $ebx\n" 13156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Allocate frame space, and save %edi. 13166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n" 13176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Put the return address in %edi. 13186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI 4005 .ra: $edi\n" 13196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Save %ebp, and use it as a frame pointer. 13206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n" 13216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // The calling function. 13236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "FUNC 5000 1000 10 epictetus\n" 13246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Mark it as end of stack. 13256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n"); 13266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Provide some distinctive values for the caller's registers. 13286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy expected.esp = 0x80000000; 13296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy expected.eip = 0x40005510; 13306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy expected.ebp = 0xc0d4aab9; 13316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy expected.ebx = 0x60f20ce6; 13326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy expected.esi = 0x53d1379d; 13336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy expected.edi = 0xafbae234; 13346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // By default, registers are unchanged. 13366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context = expected; 13376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 13386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Walk the stack, using stack_section as the contents of the stack 13406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // and raw_context as the current register values. (Set 13416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // raw_context.esp to the stack's starting address.) Expect two 13426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // stack frames; in the older frame, expect the callee-saves 13436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // registers to have values matching those in 'expected'. 13446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy void CheckWalk() { 13456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy RegionFromSection(); 13466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.esp = stack_section.start().Value(); 13476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13489753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 13496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 13509753aff85a9a20dbe294529b4184d9686ec42cddSiyangXie@gmail.com &frame_symbolizer); 13516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_TRUE(walker.Walk(&call_stack)); 13526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy frames = call_stack.frames(); 13536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2U, frames->size()); 13546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13552660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 13562660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 13572660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 13582660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 13592660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("enchiridion", frame0->function_name); 13602660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(0x40004000U, frame0->function_base); 13612660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame0->windows_frame_info != NULL); 13622660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, 13632660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame0->windows_frame_info->valid); 13642660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_TRUE(frame0->cfi_frame_info != NULL); 13652660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 13662660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com 13672660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com { // To avoid reusing locals by mistake 13682660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 13692660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 13702660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 13712660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_ESP | 13722660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_EBP | 13732660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_EBX | 13742660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_ESI | 13752660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com StackFrameX86::CONTEXT_VALID_EDI), 13762660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com frame1->context_validity); 13772660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(expected.eip, frame1->context.eip); 13782660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(expected.esp, frame1->context.esp); 13792660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(expected.ebp, frame1->context.ebp); 13802660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(expected.ebx, frame1->context.ebx); 13812660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(expected.esi, frame1->context.esi); 13822660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ(expected.edi, frame1->context.edi); 13832660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com EXPECT_EQ("epictetus", frame1->function_name); 13842660caa1ad5b57ffa763a68c3b96abc10e7f16feivan.penkov@gmail.com } 13856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 13866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // The values the stack walker should find for the caller's registers. 13886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MDRawContextX86 expected; 13896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 13906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass CFI: public CFIFixture, public Test { }; 13926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 13936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4000) { 13946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 13956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 13966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x40005510) // return address 13976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 13986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004000; 13996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 14026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4001) { 14036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 14046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 14056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x60f20ce6) // saved %ebx 14066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x40005510) // return address 14076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 14086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004001; 14096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebx = 0x91aa9a8b; // callee's %ebx value 14106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 14136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4002) { 14146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 14156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 14166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x60f20ce6) // saved %ebx 14176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x40005510) // return address 14186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 14196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004002; 14206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebx = 0x53d1379d; // saved %esi 14216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.esi = 0xa5c790ed; // callee's %esi value 14226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 14256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4003) { 14266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 14276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 14286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x56ec3db7) // garbage 14296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xafbae234) // saved %edi 14306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x53d67131) // garbage 14316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x60f20ce6) // saved %ebx 14326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x40005510) // return address 14336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 14346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004003; 14356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebx = 0x53d1379d; // saved %esi 14366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.esi = 0xa97f229d; // callee's %esi 14376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.edi = 0xb05cc997; // callee's %edi 14386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 14416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// The results here should be the same as those at module offset 14426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 0x4003. 14436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4004) { 14446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 14456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 14466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xe29782c2) // garbage 14476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xafbae234) // saved %edi 14486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x5ba29ce9) // garbage 14496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x60f20ce6) // saved %ebx 14506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x40005510) // return address 14516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 14526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004004; 14536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebx = 0x53d1379d; // saved %esi 14546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.esi = 0x0fb7dc4e; // callee's %esi 14556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.edi = 0x993b4280; // callee's %edi 14566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 14596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4005) { 14606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 14616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 14626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xe29782c2) // garbage 14636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xafbae234) // saved %edi 14646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x5ba29ce9) // garbage 14656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x60f20ce6) // saved %ebx 14666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x8036cc02) // garbage 14676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 14686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004005; 14696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebx = 0x53d1379d; // saved %esi 14706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.esi = 0x0fb7dc4e; // callee's %esi 14716d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.edi = 0x40005510; // return address 14726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 14756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(CFI, At4006) { 14766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame0_ebp; 14776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Label frame1_esp = expected.esp; 14786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy stack_section 14796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xdcdd25cd) // garbage 14806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xafbae234) // saved %edi 14816d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0xc0d4aab9) // saved %ebp 14826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame0_ebp) // frame pointer points here 14836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x60f20ce6) // saved %ebx 14846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .D32(0x8036cc02) // garbage 14856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Mark(&frame1_esp); // This effectively sets stack_section.start(). 14866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.eip = 0x40004006; 14876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebp = frame0_ebp.Value(); 14886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.ebx = 0x53d1379d; // saved %esi 14896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.esi = 0x743833c9; // callee's %esi 14906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy raw_context.edi = 0x40005510; // return address 14916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CheckWalk(); 14926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 14936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1494