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 #include <assert.h> 31 #include <stdio.h> 32 33 #include <string> 34 35 #include "breakpad_googletest_includes.h" 36 #include "common/scoped_ptr.h" 37 #include "common/using_std_string.h" 38 #include "google_breakpad/processor/basic_source_line_resolver.h" 39 #include "google_breakpad/processor/code_module.h" 40 #include "google_breakpad/processor/stack_frame.h" 41 #include "google_breakpad/processor/memory_region.h" 42 #include "processor/linked_ptr.h" 43 #include "processor/logging.h" 44 #include "processor/windows_frame_info.h" 45 #include "processor/cfi_frame_info.h" 46 47 namespace { 48 49 using google_breakpad::BasicSourceLineResolver; 50 using google_breakpad::CFIFrameInfo; 51 using google_breakpad::CodeModule; 52 using google_breakpad::MemoryRegion; 53 using google_breakpad::StackFrame; 54 using google_breakpad::WindowsFrameInfo; 55 using google_breakpad::linked_ptr; 56 using google_breakpad::scoped_ptr; 57 using google_breakpad::SymbolParseHelper; 58 59 class TestCodeModule : public CodeModule { 60 public: 61 TestCodeModule(string code_file) : code_file_(code_file) {} 62 virtual ~TestCodeModule() {} 63 64 virtual uint64_t base_address() const { return 0; } 65 virtual uint64_t size() const { return 0xb000; } 66 virtual string code_file() const { return code_file_; } 67 virtual string code_identifier() const { return ""; } 68 virtual string debug_file() const { return ""; } 69 virtual string debug_identifier() const { return ""; } 70 virtual string version() const { return ""; } 71 virtual const CodeModule* Copy() const { 72 return new TestCodeModule(code_file_); 73 } 74 75 private: 76 string code_file_; 77 }; 78 79 // A mock memory region object, for use by the STACK CFI tests. 80 class MockMemoryRegion: public MemoryRegion { 81 uint64_t GetBase() const { return 0x10000; } 82 uint32_t GetSize() const { return 0x01000; } 83 bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { 84 *value = address & 0xff; 85 return true; 86 } 87 bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { 88 *value = address & 0xffff; 89 return true; 90 } 91 bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { 92 switch (address) { 93 case 0x10008: *value = 0x98ecadc3; break; // saved %ebx 94 case 0x1000c: *value = 0x878f7524; break; // saved %esi 95 case 0x10010: *value = 0x6312f9a5; break; // saved %edi 96 case 0x10014: *value = 0x10038; break; // caller's %ebp 97 case 0x10018: *value = 0xf6438648; break; // return address 98 default: *value = 0xdeadbeef; break; // junk 99 } 100 return true; 101 } 102 bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { 103 *value = address; 104 return true; 105 } 106 void Print() const { 107 assert(false); 108 } 109 }; 110 111 // Verify that, for every association in ACTUAL, EXPECTED has the same 112 // association. (That is, ACTUAL's associations should be a subset of 113 // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and 114 // ".cfa". 115 static bool VerifyRegisters( 116 const char *file, int line, 117 const CFIFrameInfo::RegisterValueMap<uint32_t> &expected, 118 const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) { 119 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; 120 a = actual.find(".cfa"); 121 if (a == actual.end()) 122 return false; 123 a = actual.find(".ra"); 124 if (a == actual.end()) 125 return false; 126 for (a = actual.begin(); a != actual.end(); a++) { 127 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = 128 expected.find(a->first); 129 if (e == expected.end()) { 130 fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", 131 file, line, a->first.c_str(), a->second); 132 return false; 133 } 134 if (e->second != a->second) { 135 fprintf(stderr, 136 "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", 137 file, line, a->first.c_str(), a->second, e->second); 138 return false; 139 } 140 // Don't complain if this doesn't recover all registers. Although 141 // the DWARF spec says that unmentioned registers are undefined, 142 // GCC uses omission to mean that they are unchanged. 143 } 144 return true; 145 } 146 147 148 static bool VerifyEmpty(const StackFrame &frame) { 149 if (frame.function_name.empty() && 150 frame.source_file_name.empty() && 151 frame.source_line == 0) 152 return true; 153 return false; 154 } 155 156 static void ClearSourceLineInfo(StackFrame *frame) { 157 frame->function_name.clear(); 158 frame->module = NULL; 159 frame->source_file_name.clear(); 160 frame->source_line = 0; 161 } 162 163 class TestBasicSourceLineResolver : public ::testing::Test { 164 public: 165 void SetUp() { 166 testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") + 167 "/src/processor/testdata"; 168 } 169 170 BasicSourceLineResolver resolver; 171 string testdata_dir; 172 }; 173 174 TEST_F(TestBasicSourceLineResolver, TestLoadAndResolve) 175 { 176 TestCodeModule module1("module1"); 177 ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); 178 ASSERT_TRUE(resolver.HasModule(&module1)); 179 TestCodeModule module2("module2"); 180 ASSERT_TRUE(resolver.LoadModule(&module2, testdata_dir + "/module2.out")); 181 ASSERT_TRUE(resolver.HasModule(&module2)); 182 183 184 StackFrame frame; 185 scoped_ptr<WindowsFrameInfo> windows_frame_info; 186 scoped_ptr<CFIFrameInfo> cfi_frame_info; 187 frame.instruction = 0x1000; 188 frame.module = NULL; 189 resolver.FillSourceLineInfo(&frame); 190 ASSERT_FALSE(frame.module); 191 ASSERT_TRUE(frame.function_name.empty()); 192 ASSERT_EQ(frame.function_base, 0U); 193 ASSERT_TRUE(frame.source_file_name.empty()); 194 ASSERT_EQ(frame.source_line, 0); 195 ASSERT_EQ(frame.source_line_base, 0U); 196 197 frame.module = &module1; 198 resolver.FillSourceLineInfo(&frame); 199 ASSERT_EQ(frame.function_name, "Function1_1"); 200 ASSERT_TRUE(frame.module); 201 ASSERT_EQ(frame.module->code_file(), "module1"); 202 ASSERT_EQ(frame.function_base, 0x1000U); 203 ASSERT_EQ(frame.source_file_name, "file1_1.cc"); 204 ASSERT_EQ(frame.source_line, 44); 205 ASSERT_EQ(frame.source_line_base, 0x1000U); 206 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 207 ASSERT_TRUE(windows_frame_info.get()); 208 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 209 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 210 ASSERT_EQ(windows_frame_info->program_string, 211 "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ ="); 212 213 ClearSourceLineInfo(&frame); 214 frame.instruction = 0x800; 215 frame.module = &module1; 216 resolver.FillSourceLineInfo(&frame); 217 ASSERT_TRUE(VerifyEmpty(frame)); 218 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 219 ASSERT_FALSE(windows_frame_info.get()); 220 221 frame.instruction = 0x1280; 222 resolver.FillSourceLineInfo(&frame); 223 ASSERT_EQ(frame.function_name, "Function1_3"); 224 ASSERT_TRUE(frame.source_file_name.empty()); 225 ASSERT_EQ(frame.source_line, 0); 226 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 227 ASSERT_TRUE(windows_frame_info.get()); 228 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN); 229 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 230 ASSERT_TRUE(windows_frame_info->program_string.empty()); 231 232 frame.instruction = 0x1380; 233 resolver.FillSourceLineInfo(&frame); 234 ASSERT_EQ(frame.function_name, "Function1_4"); 235 ASSERT_TRUE(frame.source_file_name.empty()); 236 ASSERT_EQ(frame.source_line, 0); 237 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 238 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 239 ASSERT_TRUE(windows_frame_info.get()); 240 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 241 ASSERT_FALSE(windows_frame_info->program_string.empty()); 242 243 frame.instruction = 0x2000; 244 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 245 ASSERT_FALSE(windows_frame_info.get()); 246 247 // module1 has STACK CFI records covering 3d40..3def; 248 // module2 has STACK CFI records covering 3df0..3e9f; 249 // check that FindCFIFrameInfo doesn't claim to find any outside those ranges. 250 frame.instruction = 0x3d3f; 251 frame.module = &module1; 252 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 253 ASSERT_FALSE(cfi_frame_info.get()); 254 255 frame.instruction = 0x3e9f; 256 frame.module = &module1; 257 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 258 ASSERT_FALSE(cfi_frame_info.get()); 259 260 CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; 261 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; 262 CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; 263 MockMemoryRegion memory; 264 265 // Regardless of which instruction evaluation takes place at, it 266 // should produce the same values for the caller's registers. 267 expected_caller_registers[".cfa"] = 0x1001c; 268 expected_caller_registers[".ra"] = 0xf6438648; 269 expected_caller_registers["$ebp"] = 0x10038; 270 expected_caller_registers["$ebx"] = 0x98ecadc3; 271 expected_caller_registers["$esi"] = 0x878f7524; 272 expected_caller_registers["$edi"] = 0x6312f9a5; 273 274 frame.instruction = 0x3d40; 275 frame.module = &module1; 276 current_registers.clear(); 277 current_registers["$esp"] = 0x10018; 278 current_registers["$ebp"] = 0x10038; 279 current_registers["$ebx"] = 0x98ecadc3; 280 current_registers["$esi"] = 0x878f7524; 281 current_registers["$edi"] = 0x6312f9a5; 282 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 283 ASSERT_TRUE(cfi_frame_info.get()); 284 ASSERT_TRUE(cfi_frame_info.get() 285 ->FindCallerRegs<uint32_t>(current_registers, memory, 286 &caller_registers)); 287 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 288 expected_caller_registers, caller_registers)); 289 290 frame.instruction = 0x3d41; 291 current_registers["$esp"] = 0x10014; 292 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 293 ASSERT_TRUE(cfi_frame_info.get()); 294 ASSERT_TRUE(cfi_frame_info.get() 295 ->FindCallerRegs<uint32_t>(current_registers, memory, 296 &caller_registers)); 297 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 298 expected_caller_registers, caller_registers)); 299 300 frame.instruction = 0x3d43; 301 current_registers["$ebp"] = 0x10014; 302 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 303 ASSERT_TRUE(cfi_frame_info.get()); 304 ASSERT_TRUE(cfi_frame_info.get() 305 ->FindCallerRegs<uint32_t>(current_registers, memory, 306 &caller_registers)); 307 VerifyRegisters(__FILE__, __LINE__, 308 expected_caller_registers, caller_registers); 309 310 frame.instruction = 0x3d54; 311 current_registers["$ebx"] = 0x6864f054U; 312 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 313 ASSERT_TRUE(cfi_frame_info.get()); 314 ASSERT_TRUE(cfi_frame_info.get() 315 ->FindCallerRegs<uint32_t>(current_registers, memory, 316 &caller_registers)); 317 VerifyRegisters(__FILE__, __LINE__, 318 expected_caller_registers, caller_registers); 319 320 frame.instruction = 0x3d5a; 321 current_registers["$esi"] = 0x6285f79aU; 322 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 323 ASSERT_TRUE(cfi_frame_info.get()); 324 ASSERT_TRUE(cfi_frame_info.get() 325 ->FindCallerRegs<uint32_t>(current_registers, memory, 326 &caller_registers)); 327 VerifyRegisters(__FILE__, __LINE__, 328 expected_caller_registers, caller_registers); 329 330 frame.instruction = 0x3d84; 331 current_registers["$edi"] = 0x64061449U; 332 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 333 ASSERT_TRUE(cfi_frame_info.get()); 334 ASSERT_TRUE(cfi_frame_info.get() 335 ->FindCallerRegs<uint32_t>(current_registers, memory, 336 &caller_registers)); 337 VerifyRegisters(__FILE__, __LINE__, 338 expected_caller_registers, caller_registers); 339 340 frame.instruction = 0x2900; 341 frame.module = &module1; 342 resolver.FillSourceLineInfo(&frame); 343 ASSERT_EQ(frame.function_name, string("PublicSymbol")); 344 345 frame.instruction = 0x4000; 346 frame.module = &module1; 347 resolver.FillSourceLineInfo(&frame); 348 ASSERT_EQ(frame.function_name, string("LargeFunction")); 349 350 frame.instruction = 0x2181; 351 frame.module = &module2; 352 resolver.FillSourceLineInfo(&frame); 353 ASSERT_EQ(frame.function_name, "Function2_2"); 354 ASSERT_EQ(frame.function_base, 0x2170U); 355 ASSERT_TRUE(frame.module); 356 ASSERT_EQ(frame.module->code_file(), "module2"); 357 ASSERT_EQ(frame.source_file_name, "file2_2.cc"); 358 ASSERT_EQ(frame.source_line, 21); 359 ASSERT_EQ(frame.source_line_base, 0x2180U); 360 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 361 ASSERT_TRUE(windows_frame_info.get()); 362 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 363 ASSERT_EQ(windows_frame_info->prolog_size, 1U); 364 365 frame.instruction = 0x216f; 366 resolver.FillSourceLineInfo(&frame); 367 ASSERT_EQ(frame.function_name, "Public2_1"); 368 369 ClearSourceLineInfo(&frame); 370 frame.instruction = 0x219f; 371 frame.module = &module2; 372 resolver.FillSourceLineInfo(&frame); 373 ASSERT_TRUE(frame.function_name.empty()); 374 375 frame.instruction = 0x21a0; 376 frame.module = &module2; 377 resolver.FillSourceLineInfo(&frame); 378 ASSERT_EQ(frame.function_name, "Public2_2"); 379 } 380 381 TEST_F(TestBasicSourceLineResolver, TestInvalidLoads) 382 { 383 TestCodeModule module3("module3"); 384 ASSERT_TRUE(resolver.LoadModule(&module3, 385 testdata_dir + "/module3_bad.out")); 386 ASSERT_TRUE(resolver.HasModule(&module3)); 387 ASSERT_TRUE(resolver.IsModuleCorrupt(&module3)); 388 TestCodeModule module4("module4"); 389 ASSERT_TRUE(resolver.LoadModule(&module4, 390 testdata_dir + "/module4_bad.out")); 391 ASSERT_TRUE(resolver.HasModule(&module4)); 392 ASSERT_TRUE(resolver.IsModuleCorrupt(&module4)); 393 TestCodeModule module5("module5"); 394 ASSERT_FALSE(resolver.LoadModule(&module5, 395 testdata_dir + "/invalid-filename")); 396 ASSERT_FALSE(resolver.HasModule(&module5)); 397 TestCodeModule invalidmodule("invalid-module"); 398 ASSERT_FALSE(resolver.HasModule(&invalidmodule)); 399 } 400 401 TEST_F(TestBasicSourceLineResolver, TestUnload) 402 { 403 TestCodeModule module1("module1"); 404 ASSERT_FALSE(resolver.HasModule(&module1)); 405 ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); 406 ASSERT_TRUE(resolver.HasModule(&module1)); 407 resolver.UnloadModule(&module1); 408 ASSERT_FALSE(resolver.HasModule(&module1)); 409 ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); 410 ASSERT_TRUE(resolver.HasModule(&module1)); 411 } 412 413 // Test parsing of valid FILE lines. The format is: 414 // FILE <id> <filename> 415 TEST(SymbolParseHelper, ParseFileValid) { 416 long index; 417 char *filename; 418 419 char kTestLine[] = "FILE 1 file name"; 420 ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename)); 421 EXPECT_EQ(1, index); 422 EXPECT_EQ("file name", string(filename)); 423 424 // 0 is a valid index. 425 char kTestLine1[] = "FILE 0 file name"; 426 ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename)); 427 EXPECT_EQ(0, index); 428 EXPECT_EQ("file name", string(filename)); 429 } 430 431 // Test parsing of invalid FILE lines. The format is: 432 // FILE <id> <filename> 433 TEST(SymbolParseHelper, ParseFileInvalid) { 434 long index; 435 char *filename; 436 437 // Test missing file name. 438 char kTestLine[] = "FILE 1 "; 439 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename)); 440 441 // Test bad index. 442 char kTestLine1[] = "FILE x1 file name"; 443 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename)); 444 445 // Test large index. 446 char kTestLine2[] = "FILE 123123123123123123123123 file name"; 447 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine2, &index, &filename)); 448 449 // Test negative index. 450 char kTestLine3[] = "FILE -2 file name"; 451 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine3, &index, &filename)); 452 } 453 454 // Test parsing of valid FUNC lines. The format is: 455 // FUNC <address> <size> <stack_param_size> <name> 456 TEST(SymbolParseHelper, ParseFunctionValid) { 457 uint64_t address; 458 uint64_t size; 459 long stack_param_size; 460 char *name; 461 462 char kTestLine[] = "FUNC 1 2 3 function name"; 463 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine, &address, &size, 464 &stack_param_size, &name)); 465 EXPECT_EQ(1ULL, address); 466 EXPECT_EQ(2ULL, size); 467 EXPECT_EQ(3, stack_param_size); 468 EXPECT_EQ("function name", string(name)); 469 470 // Test hex address, size, and param size. 471 char kTestLine1[] = "FUNC a1 a2 a3 function name"; 472 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine1, &address, &size, 473 &stack_param_size, &name)); 474 EXPECT_EQ(0xa1ULL, address); 475 EXPECT_EQ(0xa2ULL, size); 476 EXPECT_EQ(0xa3, stack_param_size); 477 EXPECT_EQ("function name", string(name)); 478 479 char kTestLine2[] = "FUNC 0 0 0 function name"; 480 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine2, &address, &size, 481 &stack_param_size, &name)); 482 EXPECT_EQ(0ULL, address); 483 EXPECT_EQ(0ULL, size); 484 EXPECT_EQ(0, stack_param_size); 485 EXPECT_EQ("function name", string(name)); 486 } 487 488 // Test parsing of invalid FUNC lines. The format is: 489 // FUNC <address> <size> <stack_param_size> <name> 490 TEST(SymbolParseHelper, ParseFunctionInvalid) { 491 uint64_t address; 492 uint64_t size; 493 long stack_param_size; 494 char *name; 495 496 // Test missing function name. 497 char kTestLine[] = "FUNC 1 2 3 "; 498 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine, &address, &size, 499 &stack_param_size, &name)); 500 // Test bad address. 501 char kTestLine1[] = "FUNC 1z 2 3 function name"; 502 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine1, &address, &size, 503 &stack_param_size, &name)); 504 // Test large address. 505 char kTestLine2[] = "FUNC 123123123123123123123123123 2 3 function name"; 506 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine2, &address, &size, 507 &stack_param_size, &name)); 508 // Test bad size. 509 char kTestLine3[] = "FUNC 1 z2 3 function name"; 510 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine3, &address, &size, 511 &stack_param_size, &name)); 512 // Test large size. 513 char kTestLine4[] = "FUNC 1 231231231231231231231231232 3 function name"; 514 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine4, &address, &size, 515 &stack_param_size, &name)); 516 // Test bad param size. 517 char kTestLine5[] = "FUNC 1 2 3z function name"; 518 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine5, &address, &size, 519 &stack_param_size, &name)); 520 // Test large param size. 521 char kTestLine6[] = "FUNC 1 2 312312312312312312312312323 function name"; 522 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine6, &address, &size, 523 &stack_param_size, &name)); 524 // Negative param size. 525 char kTestLine7[] = "FUNC 1 2 -5 function name"; 526 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine7, &address, &size, 527 &stack_param_size, &name)); 528 } 529 530 // Test parsing of valid lines. The format is: 531 // <address> <size> <line number> <source file id> 532 TEST(SymbolParseHelper, ParseLineValid) { 533 uint64_t address; 534 uint64_t size; 535 long line_number; 536 long source_file; 537 538 char kTestLine[] = "1 2 3 4"; 539 ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine, &address, &size, 540 &line_number, &source_file)); 541 EXPECT_EQ(1ULL, address); 542 EXPECT_EQ(2ULL, size); 543 EXPECT_EQ(3, line_number); 544 EXPECT_EQ(4, source_file); 545 546 // Test hex size and address. 547 char kTestLine1[] = "a1 a2 3 4 // some comment"; 548 ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size, 549 &line_number, &source_file)); 550 EXPECT_EQ(0xa1ULL, address); 551 EXPECT_EQ(0xa2ULL, size); 552 EXPECT_EQ(3, line_number); 553 EXPECT_EQ(4, source_file); 554 555 // 0 is a valid line number. 556 char kTestLine2[] = "a1 a2 0 4 // some comment"; 557 ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size, 558 &line_number, &source_file)); 559 EXPECT_EQ(0xa1ULL, address); 560 EXPECT_EQ(0xa2ULL, size); 561 EXPECT_EQ(0, line_number); 562 EXPECT_EQ(4, source_file); 563 } 564 565 // Test parsing of invalid lines. The format is: 566 // <address> <size> <line number> <source file id> 567 TEST(SymbolParseHelper, ParseLineInvalid) { 568 uint64_t address; 569 uint64_t size; 570 long line_number; 571 long source_file; 572 573 // Test missing source file id. 574 char kTestLine[] = "1 2 3"; 575 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine, &address, &size, 576 &line_number, &source_file)); 577 // Test bad address. 578 char kTestLine1[] = "1z 2 3 4"; 579 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size, 580 &line_number, &source_file)); 581 // Test large address. 582 char kTestLine2[] = "123123123123123123123123 2 3 4"; 583 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size, 584 &line_number, &source_file)); 585 // Test bad size. 586 char kTestLine3[] = "1 z2 3 4"; 587 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine3, &address, &size, 588 &line_number, &source_file)); 589 // Test large size. 590 char kTestLine4[] = "1 123123123123123123123123 3 4"; 591 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine4, &address, &size, 592 &line_number, &source_file)); 593 // Test bad line number. 594 char kTestLine5[] = "1 2 z3 4"; 595 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine5, &address, &size, 596 &line_number, &source_file)); 597 // Test negative line number. 598 char kTestLine6[] = "1 2 -1 4"; 599 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine6, &address, &size, 600 &line_number, &source_file)); 601 // Test large line number. 602 char kTestLine7[] = "1 2 123123123123123123123 4"; 603 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine7, &address, &size, 604 &line_number, &source_file)); 605 // Test bad source file id. 606 char kTestLine8[] = "1 2 3 f"; 607 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine8, &address, &size, 608 &line_number, &source_file)); 609 } 610 611 // Test parsing of valid PUBLIC lines. The format is: 612 // PUBLIC <address> <stack_param_size> <name> 613 TEST(SymbolParseHelper, ParsePublicSymbolValid) { 614 uint64_t address; 615 long stack_param_size; 616 char *name; 617 618 char kTestLine[] = "PUBLIC 1 2 3"; 619 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &address, 620 &stack_param_size, &name)); 621 EXPECT_EQ(1ULL, address); 622 EXPECT_EQ(2, stack_param_size); 623 EXPECT_EQ("3", string(name)); 624 625 // Test hex size and address. 626 char kTestLine1[] = "PUBLIC a1 a2 function name"; 627 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &address, 628 &stack_param_size, &name)); 629 EXPECT_EQ(0xa1ULL, address); 630 EXPECT_EQ(0xa2, stack_param_size); 631 EXPECT_EQ("function name", string(name)); 632 633 // Test 0 is a valid address. 634 char kTestLine2[] = "PUBLIC 0 a2 function name"; 635 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &address, 636 &stack_param_size, &name)); 637 EXPECT_EQ(0ULL, address); 638 EXPECT_EQ(0xa2, stack_param_size); 639 EXPECT_EQ("function name", string(name)); 640 } 641 642 // Test parsing of invalid PUBLIC lines. The format is: 643 // PUBLIC <address> <stack_param_size> <name> 644 TEST(SymbolParseHelper, ParsePublicSymbolInvalid) { 645 uint64_t address; 646 long stack_param_size; 647 char *name; 648 649 // Test missing source function name. 650 char kTestLine[] = "PUBLIC 1 2 "; 651 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &address, 652 &stack_param_size, &name)); 653 // Test bad address. 654 char kTestLine1[] = "PUBLIC 1z 2 3"; 655 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &address, 656 &stack_param_size, &name)); 657 // Test large address. 658 char kTestLine2[] = "PUBLIC 123123123123123123123123 2 3"; 659 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &address, 660 &stack_param_size, &name)); 661 // Test bad param stack size. 662 char kTestLine3[] = "PUBLIC 1 z2 3"; 663 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &address, 664 &stack_param_size, &name)); 665 // Test large param stack size. 666 char kTestLine4[] = "PUBLIC 1 123123123123123123123123123 3"; 667 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine4, &address, 668 &stack_param_size, &name)); 669 // Test negative param stack size. 670 char kTestLine5[] = "PUBLIC 1 -5 3"; 671 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine5, &address, 672 &stack_param_size, &name)); 673 } 674 675 } // namespace 676 677 int main(int argc, char *argv[]) { 678 ::testing::InitGoogleTest(&argc, argv); 679 return RUN_ALL_TESTS(); 680 } 681