stackwalker_x86_unittest.cc revision 3108b9dd7bbac28dd01d78f9264fe494ee9c95a0
1// Copyright (c) 2010, Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 31 32// stackwalker_x86_unittest.cc: Unit tests for StackwalkerX86 class. 33 34#include <string> 35#include <vector> 36 37#include "breakpad_googletest_includes.h" 38#include "common/test_assembler.h" 39#include "common/using_std_string.h" 40#include "google_breakpad/common/minidump_format.h" 41#include "google_breakpad/processor/basic_source_line_resolver.h" 42#include "google_breakpad/processor/call_stack.h" 43#include "google_breakpad/processor/source_line_resolver_interface.h" 44#include "google_breakpad/processor/stack_frame_cpu.h" 45#include "processor/stackwalker_unittest_utils.h" 46#include "processor/stackwalker_x86.h" 47#include "processor/windows_frame_info.h" 48 49using google_breakpad::BasicSourceLineResolver; 50using google_breakpad::CallStack; 51using google_breakpad::StackFrameSymbolizer; 52using google_breakpad::StackFrame; 53using google_breakpad::StackFrameX86; 54using google_breakpad::StackwalkerX86; 55using google_breakpad::SystemInfo; 56using google_breakpad::WindowsFrameInfo; 57using google_breakpad::test_assembler::kLittleEndian; 58using google_breakpad::test_assembler::Label; 59using google_breakpad::test_assembler::Section; 60using std::vector; 61using testing::_; 62using testing::Return; 63using testing::SetArgumentPointee; 64using testing::Test; 65 66class StackwalkerX86Fixture { 67 public: 68 StackwalkerX86Fixture() 69 : stack_section(kLittleEndian), 70 // Give the two modules reasonable standard locations and names 71 // for tests to play with. 72 module1(0x40000000, 0x10000, "module1", "version1"), 73 module2(0x50000000, 0x10000, "module2", "version2"), 74 module3(0x771d0000, 0x180000, "module3", "version3"), 75 module4(0x75f90000, 0x46000, "module4", "version4"), 76 module5(0x75730000, 0x110000, "module5", "version5"), 77 module6(0x647f0000, 0x1ba8000, "module6", "version6") { 78 // Identify the system as a Linux system. 79 system_info.os = "Linux"; 80 system_info.os_short = "linux"; 81 system_info.os_version = "Salacious Skink"; 82 system_info.cpu = "x86"; 83 system_info.cpu_info = ""; 84 85 // Put distinctive values in the raw CPU context. 86 BrandContext(&raw_context); 87 88 // Create some modules with some stock debugging information. 89 modules.Add(&module1); 90 modules.Add(&module2); 91 modules.Add(&module3); 92 modules.Add(&module4); 93 modules.Add(&module5); 94 modules.Add(&module6); 95 96 // By default, none of the modules have symbol info; call 97 // SetModuleSymbols to override this. 98 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _)) 99 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); 100 } 101 102 // Set the Breakpad symbol information that supplier should return for 103 // MODULE to INFO. 104 void SetModuleSymbols(MockCodeModule *module, const string &info) { 105 char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info); 106 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _)) 107 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), 108 Return(MockSymbolSupplier::FOUND))); 109 } 110 111 // Populate stack_region with the contents of stack_section. Use 112 // stack_section.start() as the region's starting address. 113 void RegionFromSection() { 114 string contents; 115 ASSERT_TRUE(stack_section.GetContents(&contents)); 116 stack_region.Init(stack_section.start().Value(), contents); 117 } 118 119 // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. 120 void BrandContext(MDRawContextX86 *raw_context) { 121 u_int8_t x = 173; 122 for (size_t i = 0; i < sizeof(*raw_context); i++) 123 reinterpret_cast<u_int8_t *>(raw_context)[i] = (x += 17); 124 } 125 126 SystemInfo system_info; 127 MDRawContextX86 raw_context; 128 Section stack_section; 129 MockMemoryRegion stack_region; 130 MockCodeModule module1; 131 MockCodeModule module2; 132 MockCodeModule module3; 133 MockCodeModule module4; 134 MockCodeModule module5; 135 MockCodeModule module6; 136 MockCodeModules modules; 137 MockSymbolSupplier supplier; 138 BasicSourceLineResolver resolver; 139 CallStack call_stack; 140 const vector<StackFrame *> *frames; 141}; 142 143class SanityCheck: public StackwalkerX86Fixture, public Test { }; 144 145TEST_F(SanityCheck, NoResolver) { 146 stack_section.start() = 0x80000000; 147 stack_section.D32(0).D32(0); // end-of-stack marker 148 RegionFromSection(); 149 raw_context.eip = 0x40000200; 150 raw_context.ebp = 0x80000000; 151 152 StackFrameSymbolizer frame_symbolizer(NULL, NULL); 153 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 154 &frame_symbolizer); 155 // This should succeed, even without a resolver or supplier. 156 ASSERT_TRUE(walker.Walk(&call_stack)); 157 frames = call_stack.frames(); 158 StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); 159 // Check that the values from the original raw context made it 160 // through to the context in the stack frame. 161 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 162} 163 164class GetContextFrame: public StackwalkerX86Fixture, public Test { }; 165 166TEST_F(GetContextFrame, Simple) { 167 stack_section.start() = 0x80000000; 168 stack_section.D32(0).D32(0); // end-of-stack marker 169 RegionFromSection(); 170 raw_context.eip = 0x40000200; 171 raw_context.ebp = 0x80000000; 172 173 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 174 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 175 &frame_symbolizer); 176 ASSERT_TRUE(walker.Walk(&call_stack)); 177 frames = call_stack.frames(); 178 StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); 179 // Check that the values from the original raw context made it 180 // through to the context in the stack frame. 181 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); 182} 183 184class GetCallerFrame: public StackwalkerX86Fixture, public Test { }; 185 186// Walk a traditional frame. A traditional frame saves the caller's 187// %ebp just below the return address, and has its own %ebp pointing 188// at the saved %ebp. 189TEST_F(GetCallerFrame, Traditional) { 190 stack_section.start() = 0x80000000; 191 Label frame0_ebp, frame1_ebp; 192 stack_section 193 .Append(12, 0) // frame 0: space 194 .Mark(&frame0_ebp) // frame 0 %ebp points here 195 .D32(frame1_ebp) // frame 0: saved %ebp 196 .D32(0x40008679) // frame 0: return address 197 .Append(8, 0) // frame 1: space 198 .Mark(&frame1_ebp) // frame 1 %ebp points here 199 .D32(0) // frame 1: saved %ebp (stack end) 200 .D32(0); // frame 1: return address (stack end) 201 RegionFromSection(); 202 raw_context.eip = 0x4000c7a5; 203 raw_context.esp = stack_section.start().Value(); 204 raw_context.ebp = frame0_ebp.Value(); 205 206 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 207 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 208 &frame_symbolizer); 209 ASSERT_TRUE(walker.Walk(&call_stack)); 210 frames = call_stack.frames(); 211 ASSERT_EQ(2U, frames->size()); 212 213 { // To avoid reusing locals by mistake 214 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 215 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 216 EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 217 EXPECT_EQ(0x4000c7a5U, frame0->instruction); 218 EXPECT_EQ(0x4000c7a5U, frame0->context.eip); 219 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 220 EXPECT_EQ(NULL, frame0->windows_frame_info); 221 } 222 223 { // To avoid reusing locals by mistake 224 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 225 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 226 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 227 | StackFrameX86::CONTEXT_VALID_ESP 228 | StackFrameX86::CONTEXT_VALID_EBP), 229 frame1->context_validity); 230 EXPECT_EQ(0x40008679U, frame1->instruction + 1); 231 EXPECT_EQ(0x40008679U, frame1->context.eip); 232 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 233 EXPECT_EQ(NULL, frame1->windows_frame_info); 234 } 235} 236 237// Walk a traditional frame, but use a bogus %ebp value, forcing a scan 238// of the stack for something that looks like a return address. 239TEST_F(GetCallerFrame, TraditionalScan) { 240 stack_section.start() = 0x80000000; 241 Label frame1_ebp; 242 stack_section 243 // frame 0 244 .D32(0xf065dc76) // locals area: 245 .D32(0x46ee2167) // garbage that doesn't look like 246 .D32(0xbab023ec) // a return address 247 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) 248 .D32(0x4000129d) // return address 249 // frame 1 250 .Append(8, 0) // space 251 .Mark(&frame1_ebp) // %ebp points here 252 .D32(0) // saved %ebp (stack end) 253 .D32(0); // return address (stack end) 254 255 RegionFromSection(); 256 raw_context.eip = 0x4000f49d; 257 raw_context.esp = stack_section.start().Value(); 258 // Make the frame pointer bogus, to make the stackwalker scan the stack 259 // for something that looks like a return address. 260 raw_context.ebp = 0xd43eed6e; 261 262 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 263 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 264 &frame_symbolizer); 265 ASSERT_TRUE(walker.Walk(&call_stack)); 266 frames = call_stack.frames(); 267 ASSERT_EQ(2U, frames->size()); 268 269 { // To avoid reusing locals by mistake 270 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 271 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 272 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 273 EXPECT_EQ(0x4000f49dU, frame0->instruction); 274 EXPECT_EQ(0x4000f49dU, frame0->context.eip); 275 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 276 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); 277 EXPECT_EQ(NULL, frame0->windows_frame_info); 278 } 279 280 { // To avoid reusing locals by mistake 281 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 282 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 283 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 284 // walker does not actually fetch the EBP after a scan (forcing the 285 // next frame to be scanned as well). But let's grandfather the existing 286 // behavior in for now. 287 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 288 | StackFrameX86::CONTEXT_VALID_ESP 289 | StackFrameX86::CONTEXT_VALID_EBP), 290 frame1->context_validity); 291 EXPECT_EQ(0x4000129dU, frame1->instruction + 1); 292 EXPECT_EQ(0x4000129dU, frame1->context.eip); 293 EXPECT_EQ(0x80000014U, frame1->context.esp); 294 EXPECT_EQ(0xd43eed6eU, frame1->context.ebp); 295 EXPECT_EQ(NULL, frame1->windows_frame_info); 296 } 297} 298 299// Force scanning for a return address a long way down the stack 300TEST_F(GetCallerFrame, TraditionalScanLongWay) { 301 stack_section.start() = 0x80000000; 302 Label frame1_ebp; 303 stack_section 304 // frame 0 305 .D32(0xf065dc76) // locals area: 306 .D32(0x46ee2167) // garbage that doesn't look like 307 .D32(0xbab023ec) // a return address 308 .Append(20 * 4, 0) // a bunch of space 309 .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) 310 .D32(0x4000129d) // return address 311 // frame 1 312 .Append(8, 0) // space 313 .Mark(&frame1_ebp) // %ebp points here 314 .D32(0) // saved %ebp (stack end) 315 .D32(0); // return address (stack end) 316 317 RegionFromSection(); 318 raw_context.eip = 0x4000f49d; 319 raw_context.esp = stack_section.start().Value(); 320 // Make the frame pointer bogus, to make the stackwalker scan the stack 321 // for something that looks like a return address. 322 raw_context.ebp = 0xd43eed6e; 323 324 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 325 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 326 &frame_symbolizer); 327 ASSERT_TRUE(walker.Walk(&call_stack)); 328 frames = call_stack.frames(); 329 ASSERT_EQ(2U, frames->size()); 330 331 { // To avoid reusing locals by mistake 332 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 333 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 334 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 335 EXPECT_EQ(0x4000f49dU, frame0->instruction); 336 EXPECT_EQ(0x4000f49dU, frame0->context.eip); 337 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 338 EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); 339 EXPECT_EQ(NULL, frame0->windows_frame_info); 340 } 341 342 { // To avoid reusing locals by mistake 343 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 344 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 345 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 346 // walker does not actually fetch the EBP after a scan (forcing the 347 // next frame to be scanned as well). But let's grandfather the existing 348 // behavior in for now. 349 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 350 | StackFrameX86::CONTEXT_VALID_ESP 351 | StackFrameX86::CONTEXT_VALID_EBP), 352 frame1->context_validity); 353 EXPECT_EQ(0x4000129dU, frame1->instruction + 1); 354 EXPECT_EQ(0x4000129dU, frame1->context.eip); 355 EXPECT_EQ(0x80000064U, frame1->context.esp); 356 EXPECT_EQ(0xd43eed6eU, frame1->context.ebp); 357 EXPECT_EQ(NULL, frame1->windows_frame_info); 358 } 359} 360 361// Use Windows frame data (a "STACK WIN 4" record, from a 362// FrameTypeFrameData DIA record) to walk a stack frame. 363TEST_F(GetCallerFrame, WindowsFrameData) { 364 SetModuleSymbols(&module1, 365 "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" 366 " $T2 $esp .cbSavedRegs + =" 367 " $T0 .raSearchStart =" 368 " $eip $T0 ^ =" 369 " $esp $T0 4 + =" 370 " $ebx $T2 4 - ^ =" 371 " $edi $T2 8 - ^ =" 372 " $esi $T2 12 - ^ =" 373 " $ebp $T2 16 - ^ =\n"); 374 Label frame1_esp, frame1_ebp; 375 stack_section.start() = 0x80000000; 376 stack_section 377 // frame 0 378 .D32(frame1_ebp) // saved regs: %ebp 379 .D32(0xa7120d1a) // %esi 380 .D32(0x630891be) // %edi 381 .D32(0x9068a878) // %ebx 382 .D32(0xa08ea45f) // locals: unused 383 .D32(0x40001350) // return address 384 // frame 1 385 .Mark(&frame1_esp) 386 .Append(12, 0) // empty space 387 .Mark(&frame1_ebp) 388 .D32(0) // saved %ebp (stack end) 389 .D32(0); // saved %eip (stack end) 390 391 RegionFromSection(); 392 raw_context.eip = 0x4000aa85; 393 raw_context.esp = stack_section.start().Value(); 394 raw_context.ebp = 0xf052c1de; // should not be needed to walk frame 395 396 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 397 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 398 &frame_symbolizer); 399 ASSERT_TRUE(walker.Walk(&call_stack)); 400 frames = call_stack.frames(); 401 ASSERT_EQ(2U, frames->size()); 402 403 { // To avoid reusing locals by mistake 404 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 405 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 406 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 407 EXPECT_EQ(0x4000aa85U, frame0->instruction); 408 EXPECT_EQ(0x4000aa85U, frame0->context.eip); 409 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 410 EXPECT_EQ(0xf052c1deU, frame0->context.ebp); 411 EXPECT_TRUE(frame0->windows_frame_info != NULL); 412 } 413 414 { // To avoid reusing locals by mistake 415 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 416 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 417 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 418 | StackFrameX86::CONTEXT_VALID_ESP 419 | StackFrameX86::CONTEXT_VALID_EBP 420 | StackFrameX86::CONTEXT_VALID_EBX 421 | StackFrameX86::CONTEXT_VALID_ESI 422 | StackFrameX86::CONTEXT_VALID_EDI), 423 frame1->context_validity); 424 EXPECT_EQ(0x40001350U, frame1->instruction + 1); 425 EXPECT_EQ(0x40001350U, frame1->context.eip); 426 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 427 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 428 EXPECT_EQ(0x9068a878U, frame1->context.ebx); 429 EXPECT_EQ(0xa7120d1aU, frame1->context.esi); 430 EXPECT_EQ(0x630891beU, frame1->context.edi); 431 EXPECT_EQ(NULL, frame1->windows_frame_info); 432 } 433} 434 435// Use Windows frame data (a "STACK WIN 4" record, from a 436// FrameTypeFrameData DIA record) to walk a stack frame where the stack 437// is aligned and we must search 438TEST_F(GetCallerFrame, WindowsFrameDataAligned) { 439 SetModuleSymbols(&module1, 440 "STACK WIN 4 aa85 176 0 0 4 4 8 0 1" 441 " $T1 .raSearch =" 442 " $T0 $T1 4 - 8 @ =" 443 " $ebp $T1 4 - ^ =" 444 " $eip $T1 ^ =" 445 " $esp $T1 4 + ="); 446 Label frame1_esp, frame1_ebp; 447 stack_section.start() = 0x80000000; 448 stack_section 449 // frame 0 450 .D32(0x0ffa0ffa) // unused saved register 451 .D32(0xdeaddead) // locals 452 .D32(0xbeefbeef) 453 .D32(0) // 8-byte alignment 454 .D32(frame1_ebp) 455 .D32(0x5000129d) // return address 456 // frame 1 457 .Mark(&frame1_esp) 458 .D32(0x1) // parameter 459 .Mark(&frame1_ebp) 460 .D32(0) // saved %ebp (stack end) 461 .D32(0); // saved %eip (stack end) 462 463 RegionFromSection(); 464 raw_context.eip = 0x4000aa85; 465 raw_context.esp = stack_section.start().Value(); 466 raw_context.ebp = 0xf052c1de; // should not be needed to walk frame 467 468 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 469 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 470 &frame_symbolizer); 471 ASSERT_TRUE(walker.Walk(&call_stack)); 472 frames = call_stack.frames(); 473 ASSERT_EQ(2U, frames->size()); 474 475 { // To avoid reusing locals by mistake 476 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 477 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 478 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 479 EXPECT_EQ(0x4000aa85U, frame0->instruction); 480 EXPECT_EQ(0x4000aa85U, frame0->context.eip); 481 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 482 EXPECT_EQ(0xf052c1deU, frame0->context.ebp); 483 EXPECT_TRUE(frame0->windows_frame_info != NULL); 484 } 485 486 { // To avoid reusing locals by mistake 487 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 488 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 489 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 490 | StackFrameX86::CONTEXT_VALID_ESP 491 | StackFrameX86::CONTEXT_VALID_EBP), 492 frame1->context_validity); 493 EXPECT_EQ(0x5000129dU, frame1->instruction + 1); 494 EXPECT_EQ(0x5000129dU, frame1->context.eip); 495 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 496 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 497 EXPECT_EQ(NULL, frame1->windows_frame_info); 498 } 499} 500 501// Use Windows frame data (a "STACK WIN 4" record, from a 502// FrameTypeFrameData DIA record) to walk a frame, and depend on the 503// parameter size from the callee as well. 504TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { 505 SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n"); 506 SetModuleSymbols(&module2, 507 // Note bogus parameter size in FUNC record; the stack walker 508 // should prefer the STACK WIN record, and see '4' below. 509 "FUNC aa85 176 beef module2::whine\n" 510 "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" 511 " $T2 $esp .cbLocals + .cbSavedRegs + =" 512 " $T0 .raSearchStart =" 513 " $eip $T0 ^ =" 514 " $esp $T0 4 + =" 515 " $ebp $T0 20 - ^ =" 516 " $ebx $T0 8 - ^ =\n"); 517 Label frame0_esp, frame0_ebp; 518 Label frame1_esp; 519 Label frame2_esp, frame2_ebp; 520 stack_section.start() = 0x80000000; 521 stack_section 522 // frame 0, in module1::wheedle. Traditional frame. 523 .Mark(&frame0_esp) 524 .Append(16, 0) // frame space 525 .Mark(&frame0_ebp) 526 .D32(0x6fa902e0) // saved %ebp. Not a frame pointer. 527 .D32(0x5000aa95) // return address, in module2::whine 528 // frame 1, in module2::whine. FrameData frame. 529 .Mark(&frame1_esp) 530 .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle 531 .D32(0xbdc92f9f) // argument 2 532 .D32(0x0b1d8442) // argument 1 533 .D32(frame2_ebp) // saved %ebp 534 .D32(0xb1b90a15) // unused 535 .D32(0xf18e072d) // unused 536 .D32(0x2558c7f3) // saved %ebx 537 .D32(0x0365e25e) // unused 538 .D32(0x2a179e38) // return address; $T0 points here 539 // frame 2, in no module 540 .Mark(&frame2_esp) 541 .Append(12, 0) // empty space 542 .Mark(&frame2_ebp) 543 .D32(0) // saved %ebp (stack end) 544 .D32(0); // saved %eip (stack end) 545 546 RegionFromSection(); 547 raw_context.eip = 0x40001004; // in module1::wheedle 548 raw_context.esp = stack_section.start().Value(); 549 raw_context.ebp = frame0_ebp.Value(); 550 551 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 552 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 553 &frame_symbolizer); 554 ASSERT_TRUE(walker.Walk(&call_stack)); 555 frames = call_stack.frames(); 556 ASSERT_EQ(3U, frames->size()); 557 558 { // To avoid reusing locals by mistake 559 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 560 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 561 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 562 EXPECT_EQ(0x40001004U, frame0->instruction); 563 EXPECT_EQ(0x40001004U, frame0->context.eip); 564 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 565 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 566 EXPECT_EQ(&module1, frame0->module); 567 EXPECT_EQ("module1::wheedle", frame0->function_name); 568 EXPECT_EQ(0x40001000U, frame0->function_base); 569 // The FUNC record for module1::wheedle should have produced a 570 // WindowsFrameInfo structure with only the parameter size valid. 571 ASSERT_TRUE(frame0->windows_frame_info != NULL); 572 EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, 573 frame0->windows_frame_info->valid); 574 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN, 575 frame0->windows_frame_info->type_); 576 EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size); 577 } 578 579 { // To avoid reusing locals by mistake 580 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 581 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); 582 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 583 | StackFrameX86::CONTEXT_VALID_ESP 584 | StackFrameX86::CONTEXT_VALID_EBP), 585 frame1->context_validity); 586 EXPECT_EQ(0x5000aa95U, frame1->instruction + 1); 587 EXPECT_EQ(0x5000aa95U, frame1->context.eip); 588 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 589 EXPECT_EQ(0x6fa902e0U, frame1->context.ebp); 590 EXPECT_EQ(&module2, frame1->module); 591 EXPECT_EQ("module2::whine", frame1->function_name); 592 EXPECT_EQ(0x5000aa85U, frame1->function_base); 593 ASSERT_TRUE(frame1->windows_frame_info != NULL); 594 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 595 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 596 frame1->windows_frame_info->type_); 597 // This should not see the 0xbeef parameter size from the FUNC 598 // record, but should instead see the STACK WIN record. 599 EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size); 600 } 601 602 { // To avoid reusing locals by mistake 603 StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); 604 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 605 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 606 | StackFrameX86::CONTEXT_VALID_ESP 607 | StackFrameX86::CONTEXT_VALID_EBP 608 | StackFrameX86::CONTEXT_VALID_EBX), 609 frame2->context_validity); 610 EXPECT_EQ(0x2a179e38U, frame2->instruction + 1); 611 EXPECT_EQ(0x2a179e38U, frame2->context.eip); 612 EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); 613 EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp); 614 EXPECT_EQ(0x2558c7f3U, frame2->context.ebx); 615 EXPECT_EQ(NULL, frame2->module); 616 EXPECT_EQ(NULL, frame2->windows_frame_info); 617 } 618} 619 620// Use Windows frame data (a "STACK WIN 4" record, from a 621// FrameTypeFrameData DIA record) to walk a stack frame, where the 622// expression fails to yield both an $eip and an $ebp value, and the stack 623// walker must scan. 624TEST_F(GetCallerFrame, WindowsFrameDataScan) { 625 SetModuleSymbols(&module1, 626 "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n"); 627 // Mark frame 1's PC as the end of the stack. 628 SetModuleSymbols(&module2, 629 "FUNC 7c38 accf 0 module2::function\n" 630 "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n"); 631 Label frame1_esp; 632 stack_section.start() = 0x80000000; 633 stack_section 634 // frame 0 635 .Append(16, 0x2a) // unused, garbage 636 .D32(0x50007ce9) // return address 637 // frame 1 638 .Mark(&frame1_esp) 639 .Append(8, 0); // empty space 640 641 RegionFromSection(); 642 raw_context.eip = 0x40000c9c; 643 raw_context.esp = stack_section.start().Value(); 644 raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame 645 646 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 647 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 648 &frame_symbolizer); 649 ASSERT_TRUE(walker.Walk(&call_stack)); 650 frames = call_stack.frames(); 651 ASSERT_EQ(2U, frames->size()); 652 653 { // To avoid reusing locals by mistake 654 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 655 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 656 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 657 EXPECT_EQ(0x40000c9cU, frame0->instruction); 658 EXPECT_EQ(0x40000c9cU, frame0->context.eip); 659 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 660 EXPECT_EQ(0x2ae314cdU, frame0->context.ebp); 661 EXPECT_TRUE(frame0->windows_frame_info != NULL); 662 } 663 664 { // To avoid reusing locals by mistake 665 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 666 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); 667 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker 668 // does not actually fetch the EBP after a scan (forcing the next frame 669 // to be scanned as well). But let's grandfather the existing behavior in 670 // for now. 671 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 672 | StackFrameX86::CONTEXT_VALID_ESP 673 | StackFrameX86::CONTEXT_VALID_EBP), 674 frame1->context_validity); 675 EXPECT_EQ(0x50007ce9U, frame1->instruction + 1); 676 EXPECT_EQ(0x50007ce9U, frame1->context.eip); 677 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 678 EXPECT_TRUE(frame1->windows_frame_info != NULL); 679 } 680} 681 682// Use Windows frame data (a "STACK WIN 4" record, from a 683// FrameTypeFrameData DIA record) to walk a stack frame, where the 684// expression yields an $eip that falls outside of any module, and the 685// stack walker must scan. 686TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { 687 SetModuleSymbols(&module1, 688 "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1" 689 // A traditional frame, actually. 690 " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n"); 691 // Mark frame 1's PC as the end of the stack. 692 SetModuleSymbols(&module2, 693 "FUNC cfdb 8406 0 module2::function\n" 694 "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n"); 695 stack_section.start() = 0x80000000; 696 697 // In this stack, the context's %ebp is pointing at the wrong place, so 698 // the stack walker needs to scan to find the return address, and then 699 // scan again to find the caller's saved %ebp. 700 Label frame0_ebp, frame1_ebp, frame1_esp; 701 stack_section 702 // frame 0 703 .Append(8, 0x2a) // garbage 704 .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point 705 // at *** below 706 // The STACK WIN record says that the following two values are 707 // frame 1's saved %ebp and return address, but the %ebp is wrong; 708 // they're garbage. The stack walker will scan for the right values. 709 .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp 710 .D32(0x17847f5b) // alleged to be frame 1's return address 711 .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find 712 .D32(0x2b2b2b2b) // first word of realigned register save area 713 // *** frame 0 %ebp ought to be pointing here 714 .D32(0x2c2c2c2c) // realigned locals area 715 .D32(0x5000d000) // frame 1's real saved %eip; scan will find 716 // Frame 1, in module2::function. The STACK WIN record describes 717 // this as the oldest frame, without referring to its contents, so 718 // we needn't to provide any actual data here. 719 .Mark(&frame1_esp) 720 .Mark(&frame1_ebp) // frame 1 %ebp points here 721 // A dummy value for frame 1's %ebp to point at. The scan recognizes the 722 // saved %ebp because it points to a valid word in the stack memory region. 723 .D32(0x2d2d2d2d); 724 725 RegionFromSection(); 726 raw_context.eip = 0x40000700; 727 raw_context.esp = stack_section.start().Value(); 728 raw_context.ebp = frame0_ebp.Value(); 729 730 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 731 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 732 &frame_symbolizer); 733 ASSERT_TRUE(walker.Walk(&call_stack)); 734 frames = call_stack.frames(); 735 ASSERT_EQ(2U, frames->size()); 736 737 { // To avoid reusing locals by mistake 738 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 739 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 740 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 741 EXPECT_EQ(0x40000700U, frame0->instruction); 742 EXPECT_EQ(0x40000700U, frame0->context.eip); 743 EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); 744 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 745 EXPECT_TRUE(frame0->windows_frame_info != NULL); 746 } 747 748 { // To avoid reusing locals by mistake 749 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 750 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); 751 // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the 752 // walker does not actually fetch the EBP after a scan (forcing the 753 // next frame to be scanned as well). But let's grandfather the existing 754 // behavior in for now. 755 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 756 | StackFrameX86::CONTEXT_VALID_ESP 757 | StackFrameX86::CONTEXT_VALID_EBP), 758 frame1->context_validity); 759 EXPECT_EQ(0x5000d000U, frame1->instruction + 1); 760 EXPECT_EQ(0x5000d000U, frame1->context.eip); 761 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 762 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 763 EXPECT_TRUE(frame1->windows_frame_info != NULL); 764 } 765} 766 767// Use Windows FrameTypeFPO data to walk a stack frame for a function that 768// does not modify %ebp from the value it had in the caller. 769TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { 770 SetModuleSymbols(&module1, 771 // Note bogus parameter size in FUNC record; the walker 772 // should prefer the STACK WIN record, and see the '8' below. 773 "FUNC e8a8 100 feeb module1::discombobulated\n" 774 "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n"); 775 Label frame0_esp; 776 Label frame1_esp, frame1_ebp; 777 stack_section.start() = 0x80000000; 778 stack_section 779 // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. 780 .Mark(&frame0_esp) 781 // no outgoing parameters; this is the youngest frame. 782 .D32(0x7c521352) // four bytes of saved registers 783 .Append(0x10, 0x42) // local area 784 .D32(0x40009b5b) // return address, in module1, no function 785 // frame 1, in module1, no function. 786 .Mark(&frame1_esp) 787 .D32(0xf60ea7fc) // junk 788 .Mark(&frame1_ebp) 789 .D32(0) // saved %ebp (stack end) 790 .D32(0); // saved %eip (stack end) 791 792 RegionFromSection(); 793 raw_context.eip = 0x4000e8b8; // in module1::whine 794 raw_context.esp = stack_section.start().Value(); 795 // Frame pointer unchanged from caller. 796 raw_context.ebp = frame1_ebp.Value(); 797 798 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 799 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 800 &frame_symbolizer); 801 ASSERT_TRUE(walker.Walk(&call_stack)); 802 frames = call_stack.frames(); 803 ASSERT_EQ(2U, frames->size()); 804 805 { // To avoid reusing locals by mistake 806 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 807 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 808 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 809 EXPECT_EQ(0x4000e8b8U, frame0->instruction); 810 EXPECT_EQ(0x4000e8b8U, frame0->context.eip); 811 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 812 EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); // unchanged from caller 813 EXPECT_EQ(&module1, frame0->module); 814 EXPECT_EQ("module1::discombobulated", frame0->function_name); 815 EXPECT_EQ(0x4000e8a8U, frame0->function_base); 816 // The STACK WIN record for module1::discombobulated should have 817 // produced a fully populated WindowsFrameInfo structure. 818 ASSERT_TRUE(frame0->windows_frame_info != NULL); 819 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 820 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 821 frame0->windows_frame_info->type_); 822 EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size); 823 } 824 825 { // To avoid reusing locals by mistake 826 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 827 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 828 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 829 | StackFrameX86::CONTEXT_VALID_ESP 830 | StackFrameX86::CONTEXT_VALID_EBP), 831 frame1->context_validity); 832 EXPECT_EQ(0x40009b5bU, frame1->instruction + 1); 833 EXPECT_EQ(0x40009b5bU, frame1->context.eip); 834 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 835 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 836 EXPECT_EQ(&module1, frame1->module); 837 EXPECT_EQ("", frame1->function_name); 838 EXPECT_EQ(NULL, frame1->windows_frame_info); 839 } 840} 841 842// Use Windows FrameTypeFPO data to walk a stack frame for a function 843// that uses %ebp for its own purposes, saving the value it had in the 844// caller in the standard place in the saved register area. 845TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { 846 SetModuleSymbols(&module1, 847 // Note bogus parameter size in FUNC record; the walker 848 // should prefer the STACK WIN record, and see the '8' below. 849 "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n" 850 "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n"); 851 Label frame0_esp; 852 Label frame1_esp, frame1_ebp; 853 stack_section.start() = 0x80000000; 854 stack_section 855 // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. 856 .Mark(&frame0_esp) 857 // no outgoing parameters; this is the youngest frame. 858 .D32(frame1_ebp) // saved register area: saved %ebp 859 .D32(0xb68bd5f9) // saved register area: something else 860 .D32(0xd25d05fc) // local area 861 .D32(0x4000debe) // return address, in module1, no function 862 // frame 1, in module1, no function. 863 .Mark(&frame1_esp) 864 .D32(0xf0c9a974) // junk 865 .Mark(&frame1_ebp) 866 .D32(0) // saved %ebp (stack end) 867 .D32(0); // saved %eip (stack end) 868 869 RegionFromSection(); 870 raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens 871 raw_context.esp = stack_section.start().Value(); 872 // RaisedByTheAliens uses %ebp for its own mysterious purposes. 873 raw_context.ebp = 0xecbdd1a5; 874 875 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 876 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 877 &frame_symbolizer); 878 ASSERT_TRUE(walker.Walk(&call_stack)); 879 frames = call_stack.frames(); 880 ASSERT_EQ(2U, frames->size()); 881 882 { // To avoid reusing locals by mistake 883 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 884 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 885 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 886 EXPECT_EQ(0x40009ab8U, frame0->instruction); 887 EXPECT_EQ(0x40009ab8U, frame0->context.eip); 888 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 889 EXPECT_EQ(0xecbdd1a5, frame0->context.ebp); 890 EXPECT_EQ(&module1, frame0->module); 891 EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name); 892 EXPECT_EQ(0x40009aa8U, frame0->function_base); 893 // The STACK WIN record for module1::RaisedByTheAliens should have 894 // produced a fully populated WindowsFrameInfo structure. 895 ASSERT_TRUE(frame0->windows_frame_info != NULL); 896 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 897 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 898 frame0->windows_frame_info->type_); 899 EXPECT_EQ("", frame0->windows_frame_info->program_string); 900 EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer); 901 } 902 903 { // To avoid reusing locals by mistake 904 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 905 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 906 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 907 | StackFrameX86::CONTEXT_VALID_ESP 908 | StackFrameX86::CONTEXT_VALID_EBP), 909 frame1->context_validity); 910 EXPECT_EQ(0x4000debeU, frame1->instruction + 1); 911 EXPECT_EQ(0x4000debeU, frame1->context.eip); 912 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 913 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 914 EXPECT_EQ(&module1, frame1->module); 915 EXPECT_EQ("", frame1->function_name); 916 EXPECT_EQ(NULL, frame1->windows_frame_info); 917 } 918} 919 920// This is a regression unit test which covers a bug which has to do with 921// FPO-optimized Windows system call stubs in the context frame. There is 922// a more recent Windows system call dispatch mechanism which differs from 923// the one which is being tested here. The newer system call dispatch 924// mechanism creates an extra context frame (KiFastSystemCallRet). 925TEST_F(GetCallerFrame, WindowsFPOSystemCall) { 926 SetModuleSymbols(&module3, // ntdll.dll 927 "PUBLIC 1f8ac c ZwWaitForSingleObject\n" 928 "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n"); 929 SetModuleSymbols(&module4, // kernelbase.dll 930 "PUBLIC 109f9 c WaitForSingleObjectEx\n" 931 "PUBLIC 36590 0 _except_handler4\n" 932 "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip " 933 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 934 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" 935 "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip " 936 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 " 937 ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); 938 SetModuleSymbols(&module5, // kernel32.dll 939 "PUBLIC 11136 8 WaitForSingleObject\n" 940 "PUBLIC 11151 c WaitForSingleObjectExImplementation\n" 941 "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip " 942 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 943 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" 944 "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip " 945 "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 946 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); 947 SetModuleSymbols(&module6, // chrome.dll 948 "FILE 7038 some_file_name.h\n" 949 "FILE 839776 some_file_name.cc\n" 950 "FUNC 217fda 17 4 function_217fda\n" 951 "217fda 4 102 839776\n" 952 "FUNC 217ff1 a 4 function_217ff1\n" 953 "217ff1 0 594 7038\n" 954 "217ff1 a 596 7038\n" 955 "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n"); 956 957 Label frame0_esp, frame1_esp; 958 Label frame1_ebp, frame2_ebp, frame3_ebp; 959 stack_section.start() = 0x002ff290; 960 stack_section 961 .Mark(&frame0_esp) 962 .D32(0x771ef8c1) // EIP in frame 0 (system call) 963 .D32(0x75fa0a91) // return address of frame 0 964 .Mark(&frame1_esp) 965 .D32(0x000017b0) // args to child 966 .D32(0x00000000) 967 .D32(0x002ff2d8) 968 .D32(0x88014a2e) 969 .D32(0x002ff364) 970 .D32(0x000017b0) 971 .D32(0x00000000) 972 .D32(0x00000024) 973 .D32(0x00000001) 974 .D32(0x00000000) 975 .D32(0x00000000) 976 .D32(0x00000000) 977 .D32(0x00000000) 978 .D32(0x00000000) 979 .D32(0x00000000) 980 .D32(0x00000000) 981 .D32(0x9e3b9800) 982 .D32(0xfffffff7) 983 .D32(0x00000000) 984 .D32(0x002ff2a4) 985 .D32(0x64a07ff1) // random value to be confused with a return address 986 .D32(0x002ff8dc) 987 .D32(0x75fc6590) // random value to be confused with a return address 988 .D32(0xfdd2c6ea) 989 .D32(0x00000000) 990 .Mark(&frame1_ebp) 991 .D32(frame2_ebp) // Child EBP 992 .D32(0x75741194) // return address of frame 1 993 .D32(0x000017b0) // args to child 994 .D32(0x0036ee80) 995 .D32(0x00000000) 996 .D32(0x65bc7d14) 997 .Mark(&frame2_ebp) 998 .D32(frame3_ebp) // Child EBP 999 .D32(0x75741148) // return address of frame 2 1000 .D32(0x000017b0) // args to child 1001 .D32(0x0036ee80) 1002 .D32(0x00000000) 1003 .Mark(&frame3_ebp) 1004 .D32(0) // saved %ebp (stack end) 1005 .D32(0); // saved %eip (stack end) 1006 1007 RegionFromSection(); 1008 raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject 1009 raw_context.esp = stack_section.start().Value(); 1010 ASSERT_TRUE(raw_context.esp == frame0_esp.Value()); 1011 raw_context.ebp = frame1_ebp.Value(); 1012 1013 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1014 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1015 &frame_symbolizer); 1016 ASSERT_TRUE(walker.Walk(&call_stack)); 1017 frames = call_stack.frames(); 1018 1019 ASSERT_EQ(4U, frames->size()); 1020 1021 { // To avoid reusing locals by mistake 1022 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1023 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1024 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1025 EXPECT_EQ(0x771ef8c1U, frame0->instruction); 1026 EXPECT_EQ(0x771ef8c1U, frame0->context.eip); 1027 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1028 EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); 1029 EXPECT_EQ(&module3, frame0->module); 1030 EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name); 1031 // The STACK WIN record for module3!ZwWaitForSingleObject should have 1032 // produced a fully populated WindowsFrameInfo structure. 1033 ASSERT_TRUE(frame0->windows_frame_info != NULL); 1034 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 1035 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, 1036 frame0->windows_frame_info->type_); 1037 EXPECT_EQ("", frame0->windows_frame_info->program_string); 1038 EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); 1039 } 1040 1041 { // To avoid reusing locals by mistake 1042 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1043 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1044 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP 1045 | StackFrameX86::CONTEXT_VALID_ESP 1046 | StackFrameX86::CONTEXT_VALID_EBP), 1047 frame1->context_validity); 1048 EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1); 1049 EXPECT_EQ(0x75fa0a91U, frame1->context.eip); 1050 EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); 1051 EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); 1052 EXPECT_EQ(&module4, frame1->module); 1053 EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name); 1054 // The STACK WIN record for module4!WaitForSingleObjectEx should have 1055 // produced a fully populated WindowsFrameInfo structure. 1056 ASSERT_TRUE(frame1->windows_frame_info != NULL); 1057 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 1058 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1059 frame1->windows_frame_info->type_); 1060 EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " 1061 "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", 1062 frame1->windows_frame_info->program_string); 1063 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); 1064 } 1065} 1066 1067// Scan the stack for a better return address and potentially skip frames 1068// when the calculated return address is not in a known module. 1069// Note, that the span of this scan is somewhat arbitrarily limited to 30 1070// search words (pointers): 1071// const int kRASearchWords = 30; 1072// This means that frames can be skipped only when their size is relatively 1073// small: smaller than kRASearchWords * sizeof(InstructionType) 1074TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { 1075 MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1"); 1076 SetModuleSymbols(&msvcrt_dll, // msvcrt.dll 1077 "PUBLIC 38180 0 wcsstr\n" 1078 "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 " 1079 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1080 "- = $P $T0 4 + .cbParams + =\n"); 1081 1082 MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1"); 1083 SetModuleSymbols(&kernel32_dll, // kernel32.dll 1084 "PUBLIC efda 8 FindNextFileW\n" 1085 "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 " 1086 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1087 "- = $P $T0 4 + .cbParams + =\n"); 1088 1089 MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1"); 1090 SetModuleSymbols(&chrome_dll, // chrome.dll 1091 "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n" 1092 "e3cff 1a 711 2505\n" 1093 "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = " 1094 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " 1095 "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " 1096 "$T0 160 - ^ =\n"); 1097 1098 // Create some modules with some stock debugging information. 1099 MockCodeModules local_modules; 1100 local_modules.Add(&msvcrt_dll); 1101 local_modules.Add(&kernel32_dll); 1102 local_modules.Add(&chrome_dll); 1103 1104 Label frame0_esp; 1105 Label frame0_ebp; 1106 Label frame1_ebp; 1107 Label frame2_ebp; 1108 Label frame3_ebp; 1109 1110 stack_section.start() = 0x0932f2d0; 1111 stack_section 1112 .Mark(&frame0_esp) 1113 .D32(0x0764e000) 1114 .D32(0x0764e068) 1115 .Mark(&frame0_ebp) 1116 .D32(frame1_ebp) // Child EBP 1117 .D32(0x001767a0) // return address of frame 0 1118 // Not in known module 1119 .D32(0x0764e0c6) 1120 .D32(0x001bb1b8) 1121 .D32(0x0764e068) 1122 .D32(0x00000003) 1123 .D32(0x0764e068) 1124 .D32(0x00000003) 1125 .D32(0x07578828) 1126 .D32(0x0764e000) 1127 .D32(0x00000000) 1128 .D32(0x001c0010) 1129 .D32(0x0764e0c6) 1130 .Mark(&frame1_ebp) 1131 .D32(frame2_ebp) // Child EBP 1132 .D32(0x7c80f10f) // return address of frame 1 1133 // inside kernel32!FindNextFileW 1134 .D32(0x000008f8) 1135 .D32(0x00000000) 1136 .D32(0x00000000) 1137 .D32(0x00000000) 1138 .D32(0x0932f34c) 1139 .D32(0x0764e000) 1140 .D32(0x00001000) 1141 .D32(0x00000000) 1142 .D32(0x00000001) 1143 .D32(0x00000000) 1144 .D32(0x00000000) 1145 .D32(0x0932f6a8) 1146 .D32(0x00000000) 1147 .D32(0x0932f6d8) 1148 .D32(0x00000000) 1149 .D32(0x000000d6) 1150 .D32(0x0764e000) 1151 .D32(0x7ff9a000) 1152 .D32(0x0932f3fc) 1153 .D32(0x00000001) 1154 .D32(0x00000001) 1155 .D32(0x07578828) 1156 .D32(0x0000002e) 1157 .D32(0x0932f340) 1158 .D32(0x0932eef4) 1159 .D32(0x0932ffdc) 1160 .D32(0x7c839ad8) 1161 .D32(0x7c80f0d8) 1162 .D32(0x00000000) 1163 .Mark(&frame2_ebp) 1164 .D32(frame3_ebp) // Child EBP 1165 .D32(0x01d13f91) // return address of frame 2 1166 // inside chrome_dll!file_util::FileEnumerator::Next 1167 .D32(0x07578828) 1168 .D32(0x0932f6ac) 1169 .D32(0x0932f9c4) 1170 .D32(0x0932f9b4) 1171 .D32(0x00000000) 1172 .D32(0x00000003) 1173 .D32(0x0932f978) 1174 .D32(0x01094330) 1175 .D32(0x00000000) 1176 .D32(0x00000001) 1177 .D32(0x01094330) 1178 .D32(0x00000000) 1179 .D32(0x00000000) 1180 .D32(0x07f30000) 1181 .D32(0x01c3ba17) 1182 .D32(0x08bab840) 1183 .D32(0x07f31580) 1184 .D32(0x00000000) 1185 .D32(0x00000007) 1186 .D32(0x0932f940) 1187 .D32(0x0000002e) 1188 .D32(0x0932f40c) 1189 .D32(0x01d13b53) 1190 .D32(0x0932f958) 1191 .D32(0x00000001) 1192 .D32(0x00000007) 1193 .D32(0x0932f940) 1194 .D32(0x0000002e) 1195 .D32(0x00000000) 1196 .D32(0x0932f6ac) 1197 .D32(0x01e13ef0) 1198 .D32(0x00000001) 1199 .D32(0x00000007) 1200 .D32(0x0932f958) 1201 .D32(0x08bab840) 1202 .D32(0x0932f9b4) 1203 .D32(0x00000000) 1204 .D32(0x0932f9b4) 1205 .D32(0x000000a7) 1206 .D32(0x000000a7) 1207 .D32(0x0932f998) 1208 .D32(0x579627a2) 1209 .Mark(&frame3_ebp) 1210 .D32(0) // saved %ebp (stack end) 1211 .D32(0); // saved %eip (stack end) 1212 1213 RegionFromSection(); 1214 raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr 1215 raw_context.esp = frame0_esp.Value(); 1216 raw_context.ebp = frame0_ebp.Value(); 1217 // sanity 1218 ASSERT_TRUE(raw_context.esp == stack_section.start().Value()); 1219 ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8); 1220 1221 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1222 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, 1223 &local_modules, &frame_symbolizer); 1224 ASSERT_TRUE(walker.Walk(&call_stack)); 1225 frames = call_stack.frames(); 1226 1227 ASSERT_EQ(3U, frames->size()); 1228 1229 { // To avoid reusing locals by mistake 1230 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1231 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1232 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1233 EXPECT_EQ(0x77c181cdU, frame0->instruction); 1234 EXPECT_EQ(0x77c181cdU, frame0->context.eip); 1235 EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); 1236 EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); 1237 EXPECT_EQ(&msvcrt_dll, frame0->module); 1238 EXPECT_EQ("wcsstr", frame0->function_name); 1239 ASSERT_TRUE(frame0->windows_frame_info != NULL); 1240 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); 1241 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1242 frame0->windows_frame_info->type_); 1243 EXPECT_EQ("$T0 $ebp = $eip $T0 " 1244 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1245 "- = $P $T0 4 + .cbParams + =", 1246 frame0->windows_frame_info->program_string); 1247 // It has program string, so allocates_base_pointer is not expected 1248 EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); 1249 } 1250 1251 { // To avoid reusing locals by mistake 1252 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1253 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); 1254 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 1255 StackFrameX86::CONTEXT_VALID_ESP | 1256 StackFrameX86::CONTEXT_VALID_EBP), 1257 frame1->context_validity); 1258 EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1); 1259 EXPECT_EQ(0x7c80f10fU, frame1->context.eip); 1260 // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp. 1261 EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp); 1262 EXPECT_EQ(&kernel32_dll, frame1->module); 1263 EXPECT_EQ("FindNextFileW", frame1->function_name); 1264 ASSERT_TRUE(frame1->windows_frame_info != NULL); 1265 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); 1266 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1267 frame1->windows_frame_info->type_); 1268 EXPECT_EQ("$T0 $ebp = $eip $T0 " 1269 "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " 1270 "- = $P $T0 4 + .cbParams + =", 1271 frame1->windows_frame_info->program_string); 1272 EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); 1273 } 1274 1275 { // To avoid reusing locals by mistake 1276 StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); 1277 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); 1278 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 1279 StackFrameX86::CONTEXT_VALID_ESP | 1280 StackFrameX86::CONTEXT_VALID_EBP), 1281 frame2->context_validity); 1282 EXPECT_EQ(0x01d13f91U, frame2->instruction + 1); 1283 EXPECT_EQ(0x01d13f91U, frame2->context.eip); 1284 // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp. 1285 EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp); 1286 EXPECT_EQ(&chrome_dll, frame2->module); 1287 EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name); 1288 ASSERT_TRUE(frame2->windows_frame_info != NULL); 1289 EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); 1290 EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, 1291 frame2->windows_frame_info->type_); 1292 EXPECT_EQ("$T1 .raSearch = " 1293 "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " 1294 "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " 1295 "$T0 160 - ^ =", 1296 frame2->windows_frame_info->program_string); 1297 EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer); 1298 } 1299} 1300 1301struct CFIFixture: public StackwalkerX86Fixture { 1302 CFIFixture() { 1303 // Provide a bunch of STACK CFI records; individual tests walk to the 1304 // caller from every point in this series, expecting to find the same 1305 // set of register values. 1306 SetModuleSymbols(&module1, 1307 // The youngest frame's function. 1308 "FUNC 4000 1000 10 enchiridion\n" 1309 // Initially, just a return address. 1310 "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n" 1311 // Push %ebx. 1312 "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n" 1313 // Move %esi into %ebx. Weird, but permitted. 1314 "STACK CFI 4002 $esi: $ebx\n" 1315 // Allocate frame space, and save %edi. 1316 "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n" 1317 // Put the return address in %edi. 1318 "STACK CFI 4005 .ra: $edi\n" 1319 // Save %ebp, and use it as a frame pointer. 1320 "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n" 1321 1322 // The calling function. 1323 "FUNC 5000 1000 10 epictetus\n" 1324 // Mark it as end of stack. 1325 "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n"); 1326 1327 // Provide some distinctive values for the caller's registers. 1328 expected.esp = 0x80000000; 1329 expected.eip = 0x40005510; 1330 expected.ebp = 0xc0d4aab9; 1331 expected.ebx = 0x60f20ce6; 1332 expected.esi = 0x53d1379d; 1333 expected.edi = 0xafbae234; 1334 1335 // By default, registers are unchanged. 1336 raw_context = expected; 1337 } 1338 1339 // Walk the stack, using stack_section as the contents of the stack 1340 // and raw_context as the current register values. (Set 1341 // raw_context.esp to the stack's starting address.) Expect two 1342 // stack frames; in the older frame, expect the callee-saves 1343 // registers to have values matching those in 'expected'. 1344 void CheckWalk() { 1345 RegionFromSection(); 1346 raw_context.esp = stack_section.start().Value(); 1347 1348 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 1349 StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, 1350 &frame_symbolizer); 1351 ASSERT_TRUE(walker.Walk(&call_stack)); 1352 frames = call_stack.frames(); 1353 ASSERT_EQ(2U, frames->size()); 1354 1355 { // To avoid reusing locals by mistake 1356 StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); 1357 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); 1358 ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); 1359 EXPECT_EQ("enchiridion", frame0->function_name); 1360 EXPECT_EQ(0x40004000U, frame0->function_base); 1361 ASSERT_TRUE(frame0->windows_frame_info != NULL); 1362 ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, 1363 frame0->windows_frame_info->valid); 1364 ASSERT_TRUE(frame0->cfi_frame_info != NULL); 1365 } 1366 1367 { // To avoid reusing locals by mistake 1368 StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); 1369 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); 1370 ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | 1371 StackFrameX86::CONTEXT_VALID_ESP | 1372 StackFrameX86::CONTEXT_VALID_EBP | 1373 StackFrameX86::CONTEXT_VALID_EBX | 1374 StackFrameX86::CONTEXT_VALID_ESI | 1375 StackFrameX86::CONTEXT_VALID_EDI), 1376 frame1->context_validity); 1377 EXPECT_EQ(expected.eip, frame1->context.eip); 1378 EXPECT_EQ(expected.esp, frame1->context.esp); 1379 EXPECT_EQ(expected.ebp, frame1->context.ebp); 1380 EXPECT_EQ(expected.ebx, frame1->context.ebx); 1381 EXPECT_EQ(expected.esi, frame1->context.esi); 1382 EXPECT_EQ(expected.edi, frame1->context.edi); 1383 EXPECT_EQ("epictetus", frame1->function_name); 1384 } 1385 } 1386 1387 // The values the stack walker should find for the caller's registers. 1388 MDRawContextX86 expected; 1389}; 1390 1391class CFI: public CFIFixture, public Test { }; 1392 1393TEST_F(CFI, At4000) { 1394 Label frame1_esp = expected.esp; 1395 stack_section 1396 .D32(0x40005510) // return address 1397 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1398 raw_context.eip = 0x40004000; 1399 CheckWalk(); 1400} 1401 1402TEST_F(CFI, At4001) { 1403 Label frame1_esp = expected.esp; 1404 stack_section 1405 .D32(0x60f20ce6) // saved %ebx 1406 .D32(0x40005510) // return address 1407 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1408 raw_context.eip = 0x40004001; 1409 raw_context.ebx = 0x91aa9a8b; // callee's %ebx value 1410 CheckWalk(); 1411} 1412 1413TEST_F(CFI, At4002) { 1414 Label frame1_esp = expected.esp; 1415 stack_section 1416 .D32(0x60f20ce6) // saved %ebx 1417 .D32(0x40005510) // return address 1418 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1419 raw_context.eip = 0x40004002; 1420 raw_context.ebx = 0x53d1379d; // saved %esi 1421 raw_context.esi = 0xa5c790ed; // callee's %esi value 1422 CheckWalk(); 1423} 1424 1425TEST_F(CFI, At4003) { 1426 Label frame1_esp = expected.esp; 1427 stack_section 1428 .D32(0x56ec3db7) // garbage 1429 .D32(0xafbae234) // saved %edi 1430 .D32(0x53d67131) // garbage 1431 .D32(0x60f20ce6) // saved %ebx 1432 .D32(0x40005510) // return address 1433 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1434 raw_context.eip = 0x40004003; 1435 raw_context.ebx = 0x53d1379d; // saved %esi 1436 raw_context.esi = 0xa97f229d; // callee's %esi 1437 raw_context.edi = 0xb05cc997; // callee's %edi 1438 CheckWalk(); 1439} 1440 1441// The results here should be the same as those at module offset 1442// 0x4003. 1443TEST_F(CFI, At4004) { 1444 Label frame1_esp = expected.esp; 1445 stack_section 1446 .D32(0xe29782c2) // garbage 1447 .D32(0xafbae234) // saved %edi 1448 .D32(0x5ba29ce9) // garbage 1449 .D32(0x60f20ce6) // saved %ebx 1450 .D32(0x40005510) // return address 1451 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1452 raw_context.eip = 0x40004004; 1453 raw_context.ebx = 0x53d1379d; // saved %esi 1454 raw_context.esi = 0x0fb7dc4e; // callee's %esi 1455 raw_context.edi = 0x993b4280; // callee's %edi 1456 CheckWalk(); 1457} 1458 1459TEST_F(CFI, At4005) { 1460 Label frame1_esp = expected.esp; 1461 stack_section 1462 .D32(0xe29782c2) // garbage 1463 .D32(0xafbae234) // saved %edi 1464 .D32(0x5ba29ce9) // garbage 1465 .D32(0x60f20ce6) // saved %ebx 1466 .D32(0x8036cc02) // garbage 1467 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1468 raw_context.eip = 0x40004005; 1469 raw_context.ebx = 0x53d1379d; // saved %esi 1470 raw_context.esi = 0x0fb7dc4e; // callee's %esi 1471 raw_context.edi = 0x40005510; // return address 1472 CheckWalk(); 1473} 1474 1475TEST_F(CFI, At4006) { 1476 Label frame0_ebp; 1477 Label frame1_esp = expected.esp; 1478 stack_section 1479 .D32(0xdcdd25cd) // garbage 1480 .D32(0xafbae234) // saved %edi 1481 .D32(0xc0d4aab9) // saved %ebp 1482 .Mark(&frame0_ebp) // frame pointer points here 1483 .D32(0x60f20ce6) // saved %ebx 1484 .D32(0x8036cc02) // garbage 1485 .Mark(&frame1_esp); // This effectively sets stack_section.start(). 1486 raw_context.eip = 0x40004006; 1487 raw_context.ebp = frame0_ebp.Value(); 1488 raw_context.ebx = 0x53d1379d; // saved %esi 1489 raw_context.esi = 0x743833c9; // callee's %esi 1490 raw_context.edi = 0x40005510; // return address 1491 CheckWalk(); 1492} 1493 1494