fast_source_line_resolver_unittest.cc
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 // 29 // fast_source_line_resolver_unittest.cc: Unit tests for FastSourceLineResolver. 30 // Two different approaches for testing fast source line resolver: 31 // First, use the same unit test data for basic source line resolver. 32 // Second, read data from symbol files, load them as basic modules, and then 33 // serialize them and load the serialized data as fast modules. Then compare 34 // modules to assure the fast module contains exactly the same data as 35 // basic module. 36 // 37 // Author: Siyang Xie (lambxsy@google.com) 38 39 #ifdef HAVE_CONFIG_H 40 #include <config.h> // Must come first 41 #endif 42 43 #include <assert.h> 44 #include <stdio.h> 45 46 #include <sstream> 47 #include <string> 48 49 #include "breakpad_googletest_includes.h" 50 #include "common/using_std_string.h" 51 #include "google_breakpad/processor/code_module.h" 52 #include "google_breakpad/processor/stack_frame.h" 53 #include "google_breakpad/processor/memory_region.h" 54 #include "processor/logging.h" 55 #include "processor/module_serializer.h" 56 #include "processor/module_comparer.h" 57 58 namespace { 59 60 using google_breakpad::SourceLineResolverBase; 61 using google_breakpad::BasicSourceLineResolver; 62 using google_breakpad::FastSourceLineResolver; 63 using google_breakpad::ModuleSerializer; 64 using google_breakpad::ModuleComparer; 65 using google_breakpad::CFIFrameInfo; 66 using google_breakpad::CodeModule; 67 using google_breakpad::MemoryRegion; 68 using google_breakpad::StackFrame; 69 using google_breakpad::WindowsFrameInfo; 70 using google_breakpad::scoped_ptr; 71 72 class TestCodeModule : public CodeModule { 73 public: 74 explicit TestCodeModule(string code_file) : code_file_(code_file) {} 75 virtual ~TestCodeModule() {} 76 77 virtual uint64_t base_address() const { return 0; } 78 virtual uint64_t size() const { return 0xb000; } 79 virtual string code_file() const { return code_file_; } 80 virtual string code_identifier() const { return ""; } 81 virtual string debug_file() const { return ""; } 82 virtual string debug_identifier() const { return ""; } 83 virtual string version() const { return ""; } 84 virtual CodeModule* Copy() const { 85 return new TestCodeModule(code_file_); 86 } 87 virtual bool is_unloaded() const { return false; } 88 virtual uint64_t shrink_down_delta() const { return 0; } 89 virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {} 90 91 private: 92 string code_file_; 93 }; 94 95 // A mock memory region object, for use by the STACK CFI tests. 96 class MockMemoryRegion: public MemoryRegion { 97 uint64_t GetBase() const { return 0x10000; } 98 uint32_t GetSize() const { return 0x01000; } 99 bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const { 100 *value = address & 0xff; 101 return true; 102 } 103 bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const { 104 *value = address & 0xffff; 105 return true; 106 } 107 bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const { 108 switch (address) { 109 case 0x10008: *value = 0x98ecadc3; break; // saved %ebx 110 case 0x1000c: *value = 0x878f7524; break; // saved %esi 111 case 0x10010: *value = 0x6312f9a5; break; // saved %edi 112 case 0x10014: *value = 0x10038; break; // caller's %ebp 113 case 0x10018: *value = 0xf6438648; break; // return address 114 default: *value = 0xdeadbeef; break; // junk 115 } 116 return true; 117 } 118 bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const { 119 *value = address; 120 return true; 121 } 122 void Print() const { 123 assert(false); 124 } 125 }; 126 127 // Verify that, for every association in ACTUAL, EXPECTED has the same 128 // association. (That is, ACTUAL's associations should be a subset of 129 // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and 130 // ".cfa". 131 static bool VerifyRegisters( 132 const char* file, int line, 133 const CFIFrameInfo::RegisterValueMap<uint32_t>& expected, 134 const CFIFrameInfo::RegisterValueMap<uint32_t>& actual) { 135 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; 136 a = actual.find(".cfa"); 137 if (a == actual.end()) 138 return false; 139 a = actual.find(".ra"); 140 if (a == actual.end()) 141 return false; 142 for (a = actual.begin(); a != actual.end(); a++) { 143 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = 144 expected.find(a->first); 145 if (e == expected.end()) { 146 fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", 147 file, line, a->first.c_str(), a->second); 148 return false; 149 } 150 if (e->second != a->second) { 151 fprintf(stderr, 152 "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", 153 file, line, a->first.c_str(), a->second, e->second); 154 return false; 155 } 156 // Don't complain if this doesn't recover all registers. Although 157 // the DWARF spec says that unmentioned registers are undefined, 158 // GCC uses omission to mean that they are unchanged. 159 } 160 return true; 161 } 162 163 static bool VerifyEmpty(const StackFrame& frame) { 164 if (frame.function_name.empty() && 165 frame.source_file_name.empty() && 166 frame.source_line == 0) 167 return true; 168 return false; 169 } 170 171 static void ClearSourceLineInfo(StackFrame* frame) { 172 frame->function_name.clear(); 173 frame->module = NULL; 174 frame->source_file_name.clear(); 175 frame->source_line = 0; 176 } 177 178 class TestFastSourceLineResolver : public ::testing::Test { 179 public: 180 void SetUp() { 181 testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") + 182 "/src/processor/testdata"; 183 } 184 185 string symbol_file(int file_index) { 186 std::stringstream ss; 187 ss << testdata_dir << "/module" << file_index << ".out"; 188 return ss.str(); 189 } 190 191 ModuleSerializer serializer; 192 BasicSourceLineResolver basic_resolver; 193 FastSourceLineResolver fast_resolver; 194 ModuleComparer module_comparer; 195 196 string testdata_dir; 197 }; 198 199 // Test adapted from basic_source_line_resolver_unittest. 200 TEST_F(TestFastSourceLineResolver, TestLoadAndResolve) { 201 TestCodeModule module1("module1"); 202 ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1))); 203 ASSERT_TRUE(basic_resolver.HasModule(&module1)); 204 // Convert module1 to fast_module: 205 ASSERT_TRUE(serializer.ConvertOneModule( 206 module1.code_file(), &basic_resolver, &fast_resolver)); 207 ASSERT_TRUE(fast_resolver.HasModule(&module1)); 208 209 TestCodeModule module2("module2"); 210 ASSERT_TRUE(basic_resolver.LoadModule(&module2, symbol_file(2))); 211 ASSERT_TRUE(basic_resolver.HasModule(&module2)); 212 // Convert module2 to fast_module: 213 ASSERT_TRUE(serializer.ConvertOneModule( 214 module2.code_file(), &basic_resolver, &fast_resolver)); 215 ASSERT_TRUE(fast_resolver.HasModule(&module2)); 216 217 StackFrame frame; 218 scoped_ptr<WindowsFrameInfo> windows_frame_info; 219 scoped_ptr<CFIFrameInfo> cfi_frame_info; 220 frame.instruction = 0x1000; 221 frame.module = NULL; 222 fast_resolver.FillSourceLineInfo(&frame, nullptr); 223 ASSERT_FALSE(frame.module); 224 ASSERT_TRUE(frame.function_name.empty()); 225 ASSERT_EQ(frame.function_base, 0U); 226 ASSERT_TRUE(frame.source_file_name.empty()); 227 ASSERT_EQ(frame.source_line, 0); 228 ASSERT_EQ(frame.source_line_base, 0U); 229 ASSERT_EQ(frame.is_multiple, false); 230 231 frame.module = &module1; 232 fast_resolver.FillSourceLineInfo(&frame, nullptr); 233 ASSERT_EQ(frame.function_name, "Function1_1"); 234 ASSERT_TRUE(frame.module); 235 ASSERT_EQ(frame.module->code_file(), "module1"); 236 ASSERT_EQ(frame.function_base, 0x1000U); 237 ASSERT_EQ(frame.source_file_name, "file1_1.cc"); 238 ASSERT_EQ(frame.source_line, 44); 239 ASSERT_EQ(frame.source_line_base, 0x1000U); 240 ASSERT_EQ(frame.is_multiple, true); 241 windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); 242 ASSERT_TRUE(windows_frame_info.get()); 243 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 244 ASSERT_EQ(windows_frame_info->program_string, 245 "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ ="); 246 247 ClearSourceLineInfo(&frame); 248 frame.instruction = 0x800; 249 frame.module = &module1; 250 fast_resolver.FillSourceLineInfo(&frame, nullptr); 251 ASSERT_TRUE(VerifyEmpty(frame)); 252 windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); 253 ASSERT_FALSE(windows_frame_info.get()); 254 255 frame.instruction = 0x1280; 256 fast_resolver.FillSourceLineInfo(&frame, nullptr); 257 ASSERT_EQ(frame.function_name, "Function1_3"); 258 ASSERT_TRUE(frame.source_file_name.empty()); 259 ASSERT_EQ(frame.source_line, 0); 260 windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); 261 ASSERT_TRUE(windows_frame_info.get()); 262 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN); 263 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 264 ASSERT_TRUE(windows_frame_info->program_string.empty()); 265 266 frame.instruction = 0x1380; 267 fast_resolver.FillSourceLineInfo(&frame, nullptr); 268 ASSERT_EQ(frame.function_name, "Function1_4"); 269 ASSERT_TRUE(frame.source_file_name.empty()); 270 ASSERT_EQ(frame.source_line, 0); 271 windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); 272 ASSERT_TRUE(windows_frame_info.get()); 273 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 274 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 275 ASSERT_FALSE(windows_frame_info->program_string.empty()); 276 277 frame.instruction = 0x2000; 278 windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); 279 ASSERT_FALSE(windows_frame_info.get()); 280 281 // module1 has STACK CFI records covering 3d40..3def; 282 // module2 has STACK CFI records covering 3df0..3e9f; 283 // check that FindCFIFrameInfo doesn't claim to find any outside those ranges. 284 frame.instruction = 0x3d3f; 285 frame.module = &module1; 286 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 287 ASSERT_FALSE(cfi_frame_info.get()); 288 289 frame.instruction = 0x3e9f; 290 frame.module = &module1; 291 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 292 ASSERT_FALSE(cfi_frame_info.get()); 293 294 CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; 295 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; 296 CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; 297 MockMemoryRegion memory; 298 299 // Regardless of which instruction evaluation takes place at, it 300 // should produce the same values for the caller's registers. 301 expected_caller_registers[".cfa"] = 0x1001c; 302 expected_caller_registers[".ra"] = 0xf6438648; 303 expected_caller_registers["$ebp"] = 0x10038; 304 expected_caller_registers["$ebx"] = 0x98ecadc3; 305 expected_caller_registers["$esi"] = 0x878f7524; 306 expected_caller_registers["$edi"] = 0x6312f9a5; 307 308 frame.instruction = 0x3d40; 309 frame.module = &module1; 310 current_registers.clear(); 311 current_registers["$esp"] = 0x10018; 312 current_registers["$ebp"] = 0x10038; 313 current_registers["$ebx"] = 0x98ecadc3; 314 current_registers["$esi"] = 0x878f7524; 315 current_registers["$edi"] = 0x6312f9a5; 316 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 317 ASSERT_TRUE(cfi_frame_info.get()); 318 ASSERT_TRUE(cfi_frame_info.get() 319 ->FindCallerRegs<uint32_t>(current_registers, memory, 320 &caller_registers)); 321 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 322 expected_caller_registers, caller_registers)); 323 324 frame.instruction = 0x3d41; 325 current_registers["$esp"] = 0x10014; 326 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 327 ASSERT_TRUE(cfi_frame_info.get()); 328 ASSERT_TRUE(cfi_frame_info.get() 329 ->FindCallerRegs<uint32_t>(current_registers, memory, 330 &caller_registers)); 331 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 332 expected_caller_registers, caller_registers)); 333 334 frame.instruction = 0x3d43; 335 current_registers["$ebp"] = 0x10014; 336 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 337 ASSERT_TRUE(cfi_frame_info.get()); 338 ASSERT_TRUE(cfi_frame_info.get() 339 ->FindCallerRegs<uint32_t>(current_registers, memory, 340 &caller_registers)); 341 VerifyRegisters(__FILE__, __LINE__, 342 expected_caller_registers, caller_registers); 343 344 frame.instruction = 0x3d54; 345 current_registers["$ebx"] = 0x6864f054U; 346 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 347 ASSERT_TRUE(cfi_frame_info.get()); 348 ASSERT_TRUE(cfi_frame_info.get() 349 ->FindCallerRegs<uint32_t>(current_registers, memory, 350 &caller_registers)); 351 VerifyRegisters(__FILE__, __LINE__, 352 expected_caller_registers, caller_registers); 353 354 frame.instruction = 0x3d5a; 355 current_registers["$esi"] = 0x6285f79aU; 356 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 357 ASSERT_TRUE(cfi_frame_info.get()); 358 ASSERT_TRUE(cfi_frame_info.get() 359 ->FindCallerRegs<uint32_t>(current_registers, memory, 360 &caller_registers)); 361 VerifyRegisters(__FILE__, __LINE__, 362 expected_caller_registers, caller_registers); 363 364 frame.instruction = 0x3d84; 365 current_registers["$edi"] = 0x64061449U; 366 cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); 367 ASSERT_TRUE(cfi_frame_info.get()); 368 ASSERT_TRUE(cfi_frame_info.get() 369 ->FindCallerRegs<uint32_t>(current_registers, memory, 370 &caller_registers)); 371 VerifyRegisters(__FILE__, __LINE__, 372 expected_caller_registers, caller_registers); 373 374 frame.instruction = 0x2900; 375 frame.module = &module1; 376 fast_resolver.FillSourceLineInfo(&frame, nullptr); 377 ASSERT_EQ(frame.function_name, string("PublicSymbol")); 378 EXPECT_EQ(frame.is_multiple, true); 379 380 frame.instruction = 0x4000; 381 frame.module = &module1; 382 fast_resolver.FillSourceLineInfo(&frame, nullptr); 383 ASSERT_EQ(frame.function_name, string("LargeFunction")); 384 385 frame.instruction = 0x2181; 386 frame.module = &module2; 387 fast_resolver.FillSourceLineInfo(&frame, nullptr); 388 ASSERT_EQ(frame.function_name, "Function2_2"); 389 ASSERT_EQ(frame.function_base, 0x2170U); 390 ASSERT_TRUE(frame.module); 391 ASSERT_EQ(frame.module->code_file(), "module2"); 392 ASSERT_EQ(frame.source_file_name, "file2_2.cc"); 393 ASSERT_EQ(frame.source_line, 21); 394 ASSERT_EQ(frame.source_line_base, 0x2180U); 395 ASSERT_EQ(frame.is_multiple, false); 396 windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); 397 ASSERT_TRUE(windows_frame_info.get()); 398 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 399 ASSERT_EQ(windows_frame_info->prolog_size, 1U); 400 401 frame.instruction = 0x216f; 402 fast_resolver.FillSourceLineInfo(&frame, nullptr); 403 ASSERT_EQ(frame.function_name, "Public2_1"); 404 EXPECT_EQ(frame.is_multiple, false); 405 406 ClearSourceLineInfo(&frame); 407 frame.instruction = 0x219f; 408 frame.module = &module2; 409 fast_resolver.FillSourceLineInfo(&frame, nullptr); 410 ASSERT_TRUE(frame.function_name.empty()); 411 412 frame.instruction = 0x21a0; 413 frame.module = &module2; 414 fast_resolver.FillSourceLineInfo(&frame, nullptr); 415 ASSERT_EQ(frame.function_name, "Public2_2"); 416 } 417 418 // Test adapted from basic_source_line_resolver_unittest. 419 TEST_F(TestFastSourceLineResolver, TestLoadAndResolveOldInlines) { 420 TestCodeModule module("linux_inline"); 421 ASSERT_TRUE(basic_resolver.LoadModule( 422 &module, testdata_dir + 423 "/symbols/linux_inline/BBA6FA10B8AAB33D00000000000000000/" 424 "linux_inline.old.sym")); 425 ASSERT_TRUE(basic_resolver.HasModule(&module)); 426 // Convert module1 to fast_module: 427 ASSERT_TRUE(serializer.ConvertOneModule(module.code_file(), &basic_resolver, 428 &fast_resolver)); 429 ASSERT_TRUE(fast_resolver.HasModule(&module)); 430 431 StackFrame frame; 432 std::deque<std::unique_ptr<StackFrame>> inlined_frames; 433 frame.instruction = 0x161b6; 434 frame.module = &module; 435 fast_resolver.FillSourceLineInfo(&frame, &inlined_frames); 436 437 // main frame. 438 ASSERT_EQ(frame.function_name, "main"); 439 ASSERT_EQ(frame.function_base, 0x15b30U); 440 ASSERT_EQ(frame.source_file_name, "linux_inline.cpp"); 441 ASSERT_EQ(frame.source_line, 42); 442 ASSERT_EQ(frame.source_line_base, 0x161b6U); 443 ASSERT_EQ(frame.is_multiple, false); 444 445 ASSERT_EQ(inlined_frames.size(), 3UL); 446 447 // Inlined frames inside main frame. 448 ASSERT_EQ(inlined_frames[2]->function_name, "foo()"); 449 ASSERT_EQ(inlined_frames[2]->function_base, 0x15b45U); 450 ASSERT_EQ(inlined_frames[2]->source_file_name, "linux_inline.cpp"); 451 ASSERT_EQ(inlined_frames[2]->source_line, 39); 452 ASSERT_EQ(inlined_frames[2]->source_line_base, 0x161b6U); 453 ASSERT_EQ(inlined_frames[2]->trust, StackFrame::FRAME_TRUST_INLINE); 454 455 ASSERT_EQ(inlined_frames[1]->function_name, "bar()"); 456 ASSERT_EQ(inlined_frames[1]->function_base, 0x15b72U); 457 ASSERT_EQ(inlined_frames[1]->source_file_name, "linux_inline.cpp"); 458 ASSERT_EQ(inlined_frames[1]->source_line, 32); 459 ASSERT_EQ(inlined_frames[1]->source_line_base, 0x161b6U); 460 ASSERT_EQ(inlined_frames[1]->trust, StackFrame::FRAME_TRUST_INLINE); 461 462 ASSERT_EQ(inlined_frames[0]->function_name, "func()"); 463 ASSERT_EQ(inlined_frames[0]->function_base, 0x15b83U); 464 ASSERT_EQ(inlined_frames[0]->source_file_name, "linux_inline.cpp"); 465 ASSERT_EQ(inlined_frames[0]->source_line, 27); 466 ASSERT_EQ(inlined_frames[0]->source_line_base, 0x161b6U); 467 ASSERT_EQ(inlined_frames[0]->trust, StackFrame::FRAME_TRUST_INLINE); 468 } 469 470 // Test adapted from basic_source_line_resolver_unittest. 471 TEST_F(TestFastSourceLineResolver, TestLoadAndResolveNewInlines) { 472 TestCodeModule module("linux_inline"); 473 ASSERT_TRUE(basic_resolver.LoadModule( 474 &module, testdata_dir + 475 "/symbols/linux_inline/BBA6FA10B8AAB33D00000000000000000/" 476 "linux_inline.new.sym")); 477 ASSERT_TRUE(basic_resolver.HasModule(&module)); 478 // Convert module1 to fast_module: 479 ASSERT_TRUE(serializer.ConvertOneModule(module.code_file(), &basic_resolver, 480 &fast_resolver)); 481 ASSERT_TRUE(fast_resolver.HasModule(&module)); 482 483 StackFrame frame; 484 std::deque<std::unique_ptr<StackFrame>> inlined_frames; 485 frame.instruction = 0x161b6; 486 frame.module = &module; 487 fast_resolver.FillSourceLineInfo(&frame, &inlined_frames); 488 489 // main frame. 490 ASSERT_EQ(frame.function_name, "main"); 491 ASSERT_EQ(frame.function_base, 0x15b30U); 492 ASSERT_EQ(frame.source_file_name, "a.cpp"); 493 ASSERT_EQ(frame.source_line, 42); 494 ASSERT_EQ(frame.source_line_base, 0x161b6U); 495 ASSERT_EQ(frame.is_multiple, false); 496 497 ASSERT_EQ(inlined_frames.size(), 3UL); 498 499 // Inlined frames inside main frame. 500 ASSERT_EQ(inlined_frames[2]->function_name, "foo()"); 501 ASSERT_EQ(inlined_frames[2]->function_base, 0x15b45U); 502 ASSERT_EQ(inlined_frames[2]->source_file_name, "b.cpp"); 503 ASSERT_EQ(inlined_frames[2]->source_line, 39); 504 ASSERT_EQ(inlined_frames[2]->source_line_base, 0x161b6U); 505 ASSERT_EQ(inlined_frames[2]->trust, StackFrame::FRAME_TRUST_INLINE); 506 507 ASSERT_EQ(inlined_frames[1]->function_name, "bar()"); 508 ASSERT_EQ(inlined_frames[1]->function_base, 0x15b72U); 509 ASSERT_EQ(inlined_frames[1]->source_file_name, "c.cpp"); 510 ASSERT_EQ(inlined_frames[1]->source_line, 32); 511 ASSERT_EQ(inlined_frames[1]->source_line_base, 0x161b6U); 512 ASSERT_EQ(inlined_frames[1]->trust, StackFrame::FRAME_TRUST_INLINE); 513 514 ASSERT_EQ(inlined_frames[0]->function_name, "func()"); 515 ASSERT_EQ(inlined_frames[0]->function_base, 0x15b83U); 516 ASSERT_EQ(inlined_frames[0]->source_file_name, "linux_inline.cpp"); 517 ASSERT_EQ(inlined_frames[0]->source_line, 27); 518 ASSERT_EQ(inlined_frames[0]->source_line_base, 0x161b6U); 519 ASSERT_EQ(inlined_frames[0]->trust, StackFrame::FRAME_TRUST_INLINE); 520 } 521 522 TEST_F(TestFastSourceLineResolver, TestInvalidLoads) { 523 TestCodeModule module3("module3"); 524 ASSERT_TRUE(basic_resolver.LoadModule(&module3, 525 testdata_dir + "/module3_bad.out")); 526 ASSERT_TRUE(basic_resolver.HasModule(&module3)); 527 ASSERT_TRUE(basic_resolver.IsModuleCorrupt(&module3)); 528 // Convert module3 to fast_module: 529 ASSERT_TRUE(serializer.ConvertOneModule(module3.code_file(), 530 &basic_resolver, 531 &fast_resolver)); 532 ASSERT_TRUE(fast_resolver.HasModule(&module3)); 533 ASSERT_TRUE(fast_resolver.IsModuleCorrupt(&module3)); 534 535 TestCodeModule module4("module4"); 536 ASSERT_TRUE(basic_resolver.LoadModule(&module4, 537 testdata_dir + "/module4_bad.out")); 538 ASSERT_TRUE(basic_resolver.HasModule(&module4)); 539 ASSERT_TRUE(basic_resolver.IsModuleCorrupt(&module4)); 540 // Convert module4 to fast_module: 541 ASSERT_TRUE(serializer.ConvertOneModule(module4.code_file(), 542 &basic_resolver, 543 &fast_resolver)); 544 ASSERT_TRUE(fast_resolver.HasModule(&module4)); 545 ASSERT_TRUE(fast_resolver.IsModuleCorrupt(&module4)); 546 547 TestCodeModule module5("module5"); 548 ASSERT_FALSE(fast_resolver.LoadModule(&module5, 549 testdata_dir + "/invalid-filename")); 550 ASSERT_FALSE(fast_resolver.HasModule(&module5)); 551 552 TestCodeModule invalidmodule("invalid-module"); 553 ASSERT_FALSE(fast_resolver.HasModule(&invalidmodule)); 554 } 555 556 TEST_F(TestFastSourceLineResolver, TestUnload) { 557 TestCodeModule module1("module1"); 558 ASSERT_FALSE(basic_resolver.HasModule(&module1)); 559 560 ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1))); 561 ASSERT_TRUE(basic_resolver.HasModule(&module1)); 562 // Convert module1 to fast_module. 563 ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(), 564 &basic_resolver, 565 &fast_resolver)); 566 ASSERT_TRUE(fast_resolver.HasModule(&module1)); 567 basic_resolver.UnloadModule(&module1); 568 fast_resolver.UnloadModule(&module1); 569 ASSERT_FALSE(fast_resolver.HasModule(&module1)); 570 571 ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1))); 572 ASSERT_TRUE(basic_resolver.HasModule(&module1)); 573 // Convert module1 to fast_module. 574 ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(), 575 &basic_resolver, 576 &fast_resolver)); 577 ASSERT_TRUE(fast_resolver.HasModule(&module1)); 578 } 579 580 TEST_F(TestFastSourceLineResolver, CompareModule) { 581 char* symbol_data; 582 size_t symbol_data_size; 583 string symbol_data_string; 584 string filename; 585 586 for (int module_index = 0; module_index < 3; ++module_index) { 587 std::stringstream ss; 588 ss << testdata_dir << "/module" << module_index << ".out"; 589 filename = ss.str(); 590 ASSERT_TRUE(SourceLineResolverBase::ReadSymbolFile( 591 symbol_file(module_index), &symbol_data, &symbol_data_size)); 592 symbol_data_string.assign(symbol_data, symbol_data_size); 593 delete [] symbol_data; 594 ASSERT_TRUE(module_comparer.Compare(symbol_data_string)); 595 } 596 } 597 598 } // namespace 599 600 int main(int argc, char* argv[]) { 601 ::testing::InitGoogleTest(&argc, argv); 602 return RUN_ALL_TESTS(); 603 }