basic_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 #ifdef HAVE_CONFIG_H 30 #include <config.h> // Must come first 31 #endif 32 33 #include <assert.h> 34 #include <stdio.h> 35 36 #include <string> 37 38 #include "breakpad_googletest_includes.h" 39 #include "common/scoped_ptr.h" 40 #include "common/using_std_string.h" 41 #include "google_breakpad/processor/basic_source_line_resolver.h" 42 #include "google_breakpad/processor/code_module.h" 43 #include "google_breakpad/processor/stack_frame.h" 44 #include "google_breakpad/processor/memory_region.h" 45 #include "processor/linked_ptr.h" 46 #include "processor/logging.h" 47 #include "processor/windows_frame_info.h" 48 #include "processor/cfi_frame_info.h" 49 50 namespace { 51 52 using google_breakpad::BasicSourceLineResolver; 53 using google_breakpad::CFIFrameInfo; 54 using google_breakpad::CodeModule; 55 using google_breakpad::MemoryRegion; 56 using google_breakpad::StackFrame; 57 using google_breakpad::WindowsFrameInfo; 58 using google_breakpad::scoped_ptr; 59 using google_breakpad::SymbolParseHelper; 60 61 class TestCodeModule : public CodeModule { 62 public: 63 TestCodeModule(string code_file) : code_file_(code_file) {} 64 virtual ~TestCodeModule() {} 65 66 virtual uint64_t base_address() const { return 0; } 67 virtual uint64_t size() const { return 0xb000; } 68 virtual string code_file() const { return code_file_; } 69 virtual string code_identifier() const { return ""; } 70 virtual string debug_file() const { return ""; } 71 virtual string debug_identifier() const { return ""; } 72 virtual string version() const { return ""; } 73 virtual CodeModule* Copy() const { 74 return new TestCodeModule(code_file_); 75 } 76 virtual bool is_unloaded() const { return false; } 77 virtual uint64_t shrink_down_delta() const { return 0; } 78 virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {} 79 80 private: 81 string code_file_; 82 }; 83 84 // A mock memory region object, for use by the STACK CFI tests. 85 class MockMemoryRegion: public MemoryRegion { 86 uint64_t GetBase() const { return 0x10000; } 87 uint32_t GetSize() const { return 0x01000; } 88 bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const { 89 *value = address & 0xff; 90 return true; 91 } 92 bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const { 93 *value = address & 0xffff; 94 return true; 95 } 96 bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const { 97 switch (address) { 98 case 0x10008: *value = 0x98ecadc3; break; // saved %ebx 99 case 0x1000c: *value = 0x878f7524; break; // saved %esi 100 case 0x10010: *value = 0x6312f9a5; break; // saved %edi 101 case 0x10014: *value = 0x10038; break; // caller's %ebp 102 case 0x10018: *value = 0xf6438648; break; // return address 103 default: *value = 0xdeadbeef; break; // junk 104 } 105 return true; 106 } 107 bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const { 108 *value = address; 109 return true; 110 } 111 void Print() const { 112 assert(false); 113 } 114 }; 115 116 // Verify that, for every association in ACTUAL, EXPECTED has the same 117 // association. (That is, ACTUAL's associations should be a subset of 118 // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and 119 // ".cfa". 120 static bool VerifyRegisters( 121 const char* file, int line, 122 const CFIFrameInfo::RegisterValueMap<uint32_t>& expected, 123 const CFIFrameInfo::RegisterValueMap<uint32_t>& actual) { 124 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; 125 a = actual.find(".cfa"); 126 if (a == actual.end()) 127 return false; 128 a = actual.find(".ra"); 129 if (a == actual.end()) 130 return false; 131 for (a = actual.begin(); a != actual.end(); a++) { 132 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = 133 expected.find(a->first); 134 if (e == expected.end()) { 135 fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", 136 file, line, a->first.c_str(), a->second); 137 return false; 138 } 139 if (e->second != a->second) { 140 fprintf(stderr, 141 "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", 142 file, line, a->first.c_str(), a->second, e->second); 143 return false; 144 } 145 // Don't complain if this doesn't recover all registers. Although 146 // the DWARF spec says that unmentioned registers are undefined, 147 // GCC uses omission to mean that they are unchanged. 148 } 149 return true; 150 } 151 152 153 static bool VerifyEmpty(const StackFrame& frame) { 154 if (frame.function_name.empty() && 155 frame.source_file_name.empty() && 156 frame.source_line == 0) 157 return true; 158 return false; 159 } 160 161 static void ClearSourceLineInfo(StackFrame* frame) { 162 frame->function_name.clear(); 163 frame->module = NULL; 164 frame->source_file_name.clear(); 165 frame->source_line = 0; 166 } 167 168 class TestBasicSourceLineResolver : public ::testing::Test { 169 public: 170 void SetUp() { 171 testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") + 172 "/src/processor/testdata"; 173 } 174 175 BasicSourceLineResolver resolver; 176 string testdata_dir; 177 }; 178 179 TEST_F(TestBasicSourceLineResolver, TestLoadAndResolve) 180 { 181 TestCodeModule module1("module1"); 182 ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); 183 ASSERT_TRUE(resolver.HasModule(&module1)); 184 TestCodeModule module2("module2"); 185 ASSERT_TRUE(resolver.LoadModule(&module2, testdata_dir + "/module2.out")); 186 ASSERT_TRUE(resolver.HasModule(&module2)); 187 188 189 StackFrame frame; 190 scoped_ptr<WindowsFrameInfo> windows_frame_info; 191 scoped_ptr<CFIFrameInfo> cfi_frame_info; 192 frame.instruction = 0x1000; 193 frame.module = NULL; 194 resolver.FillSourceLineInfo(&frame, nullptr); 195 ASSERT_FALSE(frame.module); 196 ASSERT_TRUE(frame.function_name.empty()); 197 ASSERT_EQ(frame.function_base, 0U); 198 ASSERT_TRUE(frame.source_file_name.empty()); 199 ASSERT_EQ(frame.source_line, 0); 200 ASSERT_EQ(frame.source_line_base, 0U); 201 EXPECT_EQ(frame.is_multiple, false); 202 203 frame.module = &module1; 204 resolver.FillSourceLineInfo(&frame, nullptr); 205 ASSERT_EQ(frame.function_name, "Function1_1"); 206 ASSERT_TRUE(frame.module); 207 ASSERT_EQ(frame.module->code_file(), "module1"); 208 ASSERT_EQ(frame.function_base, 0x1000U); 209 ASSERT_EQ(frame.source_file_name, "file1_1.cc"); 210 ASSERT_EQ(frame.source_line, 44); 211 ASSERT_EQ(frame.source_line_base, 0x1000U); 212 EXPECT_EQ(frame.is_multiple, true); 213 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 214 ASSERT_TRUE(windows_frame_info.get()); 215 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 216 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 217 ASSERT_EQ(windows_frame_info->program_string, 218 "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ ="); 219 220 ClearSourceLineInfo(&frame); 221 frame.instruction = 0x800; 222 frame.module = &module1; 223 resolver.FillSourceLineInfo(&frame, nullptr); 224 ASSERT_TRUE(VerifyEmpty(frame)); 225 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 226 ASSERT_FALSE(windows_frame_info.get()); 227 228 frame.instruction = 0x1280; 229 resolver.FillSourceLineInfo(&frame, nullptr); 230 ASSERT_EQ(frame.function_name, "Function1_3"); 231 ASSERT_TRUE(frame.source_file_name.empty()); 232 ASSERT_EQ(frame.source_line, 0); 233 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 234 ASSERT_TRUE(windows_frame_info.get()); 235 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN); 236 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 237 ASSERT_TRUE(windows_frame_info->program_string.empty()); 238 239 frame.instruction = 0x1380; 240 resolver.FillSourceLineInfo(&frame, nullptr); 241 ASSERT_EQ(frame.function_name, "Function1_4"); 242 ASSERT_TRUE(frame.source_file_name.empty()); 243 ASSERT_EQ(frame.source_line, 0); 244 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 245 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 246 ASSERT_TRUE(windows_frame_info.get()); 247 ASSERT_FALSE(windows_frame_info->allocates_base_pointer); 248 ASSERT_FALSE(windows_frame_info->program_string.empty()); 249 250 frame.instruction = 0x2000; 251 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 252 ASSERT_FALSE(windows_frame_info.get()); 253 254 // module1 has STACK CFI records covering 3d40..3def; 255 // module2 has STACK CFI records covering 3df0..3e9f; 256 // check that FindCFIFrameInfo doesn't claim to find any outside those ranges. 257 frame.instruction = 0x3d3f; 258 frame.module = &module1; 259 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 260 ASSERT_FALSE(cfi_frame_info.get()); 261 262 frame.instruction = 0x3e9f; 263 frame.module = &module1; 264 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 265 ASSERT_FALSE(cfi_frame_info.get()); 266 267 CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; 268 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; 269 CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; 270 MockMemoryRegion memory; 271 272 // Regardless of which instruction evaluation takes place at, it 273 // should produce the same values for the caller's registers. 274 expected_caller_registers[".cfa"] = 0x1001c; 275 expected_caller_registers[".ra"] = 0xf6438648; 276 expected_caller_registers["$ebp"] = 0x10038; 277 expected_caller_registers["$ebx"] = 0x98ecadc3; 278 expected_caller_registers["$esi"] = 0x878f7524; 279 expected_caller_registers["$edi"] = 0x6312f9a5; 280 281 frame.instruction = 0x3d40; 282 frame.module = &module1; 283 current_registers.clear(); 284 current_registers["$esp"] = 0x10018; 285 current_registers["$ebp"] = 0x10038; 286 current_registers["$ebx"] = 0x98ecadc3; 287 current_registers["$esi"] = 0x878f7524; 288 current_registers["$edi"] = 0x6312f9a5; 289 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 290 ASSERT_TRUE(cfi_frame_info.get()); 291 ASSERT_TRUE(cfi_frame_info.get() 292 ->FindCallerRegs<uint32_t>(current_registers, memory, 293 &caller_registers)); 294 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 295 expected_caller_registers, caller_registers)); 296 297 frame.instruction = 0x3d41; 298 current_registers["$esp"] = 0x10014; 299 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 300 ASSERT_TRUE(cfi_frame_info.get()); 301 ASSERT_TRUE(cfi_frame_info.get() 302 ->FindCallerRegs<uint32_t>(current_registers, memory, 303 &caller_registers)); 304 ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, 305 expected_caller_registers, caller_registers)); 306 307 frame.instruction = 0x3d43; 308 current_registers["$ebp"] = 0x10014; 309 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 310 ASSERT_TRUE(cfi_frame_info.get()); 311 ASSERT_TRUE(cfi_frame_info.get() 312 ->FindCallerRegs<uint32_t>(current_registers, memory, 313 &caller_registers)); 314 VerifyRegisters(__FILE__, __LINE__, 315 expected_caller_registers, caller_registers); 316 317 frame.instruction = 0x3d54; 318 current_registers["$ebx"] = 0x6864f054U; 319 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 320 ASSERT_TRUE(cfi_frame_info.get()); 321 ASSERT_TRUE(cfi_frame_info.get() 322 ->FindCallerRegs<uint32_t>(current_registers, memory, 323 &caller_registers)); 324 VerifyRegisters(__FILE__, __LINE__, 325 expected_caller_registers, caller_registers); 326 327 frame.instruction = 0x3d5a; 328 current_registers["$esi"] = 0x6285f79aU; 329 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 330 ASSERT_TRUE(cfi_frame_info.get()); 331 ASSERT_TRUE(cfi_frame_info.get() 332 ->FindCallerRegs<uint32_t>(current_registers, memory, 333 &caller_registers)); 334 VerifyRegisters(__FILE__, __LINE__, 335 expected_caller_registers, caller_registers); 336 337 frame.instruction = 0x3d84; 338 current_registers["$edi"] = 0x64061449U; 339 cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); 340 ASSERT_TRUE(cfi_frame_info.get()); 341 ASSERT_TRUE(cfi_frame_info.get() 342 ->FindCallerRegs<uint32_t>(current_registers, memory, 343 &caller_registers)); 344 VerifyRegisters(__FILE__, __LINE__, 345 expected_caller_registers, caller_registers); 346 347 frame.instruction = 0x2900; 348 frame.module = &module1; 349 resolver.FillSourceLineInfo(&frame, nullptr); 350 ASSERT_EQ(frame.function_name, string("PublicSymbol")); 351 EXPECT_EQ(frame.is_multiple, true); 352 353 frame.instruction = 0x4000; 354 frame.module = &module1; 355 resolver.FillSourceLineInfo(&frame, nullptr); 356 ASSERT_EQ(frame.function_name, string("LargeFunction")); 357 358 frame.instruction = 0x2181; 359 frame.module = &module2; 360 resolver.FillSourceLineInfo(&frame, nullptr); 361 ASSERT_EQ(frame.function_name, "Function2_2"); 362 ASSERT_EQ(frame.function_base, 0x2170U); 363 ASSERT_TRUE(frame.module); 364 ASSERT_EQ(frame.module->code_file(), "module2"); 365 ASSERT_EQ(frame.source_file_name, "file2_2.cc"); 366 ASSERT_EQ(frame.source_line, 21); 367 ASSERT_EQ(frame.source_line_base, 0x2180U); 368 EXPECT_EQ(frame.is_multiple, false); 369 windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); 370 ASSERT_TRUE(windows_frame_info.get()); 371 ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); 372 ASSERT_EQ(windows_frame_info->prolog_size, 1U); 373 374 frame.instruction = 0x216f; 375 resolver.FillSourceLineInfo(&frame, nullptr); 376 ASSERT_EQ(frame.function_name, "Public2_1"); 377 EXPECT_EQ(frame.is_multiple, false); 378 379 ClearSourceLineInfo(&frame); 380 frame.instruction = 0x219f; 381 frame.module = &module2; 382 resolver.FillSourceLineInfo(&frame, nullptr); 383 ASSERT_TRUE(frame.function_name.empty()); 384 385 frame.instruction = 0x21a0; 386 frame.module = &module2; 387 resolver.FillSourceLineInfo(&frame, nullptr); 388 ASSERT_EQ(frame.function_name, "Public2_2"); 389 } 390 391 TEST_F(TestBasicSourceLineResolver, TestInvalidLoads) 392 { 393 TestCodeModule module3("module3"); 394 ASSERT_TRUE(resolver.LoadModule(&module3, 395 testdata_dir + "/module3_bad.out")); 396 ASSERT_TRUE(resolver.HasModule(&module3)); 397 ASSERT_TRUE(resolver.IsModuleCorrupt(&module3)); 398 TestCodeModule module4("module4"); 399 ASSERT_TRUE(resolver.LoadModule(&module4, 400 testdata_dir + "/module4_bad.out")); 401 ASSERT_TRUE(resolver.HasModule(&module4)); 402 ASSERT_TRUE(resolver.IsModuleCorrupt(&module4)); 403 TestCodeModule module5("module5"); 404 ASSERT_FALSE(resolver.LoadModule(&module5, 405 testdata_dir + "/invalid-filename")); 406 ASSERT_FALSE(resolver.HasModule(&module5)); 407 TestCodeModule invalidmodule("invalid-module"); 408 ASSERT_FALSE(resolver.HasModule(&invalidmodule)); 409 } 410 411 TEST_F(TestBasicSourceLineResolver, TestUnload) 412 { 413 TestCodeModule module1("module1"); 414 ASSERT_FALSE(resolver.HasModule(&module1)); 415 ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); 416 ASSERT_TRUE(resolver.HasModule(&module1)); 417 resolver.UnloadModule(&module1); 418 ASSERT_FALSE(resolver.HasModule(&module1)); 419 ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); 420 ASSERT_TRUE(resolver.HasModule(&module1)); 421 } 422 423 TEST_F(TestBasicSourceLineResolver, TestLoadAndResolveOldInlines) { 424 TestCodeModule module("linux_inline"); 425 ASSERT_TRUE(resolver.LoadModule( 426 &module, testdata_dir + 427 "/symbols/linux_inline/BBA6FA10B8AAB33D00000000000000000/" 428 "linux_inline.old.sym")); 429 ASSERT_TRUE(resolver.HasModule(&module)); 430 StackFrame frame; 431 std::deque<std::unique_ptr<StackFrame>> inlined_frames; 432 frame.instruction = 0x161b6; 433 frame.module = &module; 434 // main frame. 435 resolver.FillSourceLineInfo(&frame, &inlined_frames); 436 ASSERT_EQ(frame.function_name, "main"); 437 ASSERT_EQ(frame.function_base, 0x15b30U); 438 ASSERT_EQ(frame.source_file_name, "linux_inline.cpp"); 439 ASSERT_EQ(frame.source_line, 42); 440 ASSERT_EQ(frame.source_line_base, 0x161b6U); 441 EXPECT_EQ(frame.is_multiple, false); 442 443 ASSERT_EQ(inlined_frames.size(), 3UL); 444 445 // Inlined frames inside main frame. 446 ASSERT_EQ(inlined_frames[2]->function_name, "foo()"); 447 ASSERT_EQ(inlined_frames[2]->function_base, 0x15b45U); 448 ASSERT_EQ(inlined_frames[2]->source_file_name, "linux_inline.cpp"); 449 ASSERT_EQ(inlined_frames[2]->source_line, 39); 450 ASSERT_EQ(inlined_frames[2]->source_line_base, 0x161b6U); 451 ASSERT_EQ(inlined_frames[2]->trust, StackFrame::FRAME_TRUST_INLINE); 452 453 ASSERT_EQ(inlined_frames[1]->function_name, "bar()"); 454 ASSERT_EQ(inlined_frames[1]->function_base, 0x15b72U); 455 ASSERT_EQ(inlined_frames[1]->source_file_name, "linux_inline.cpp"); 456 ASSERT_EQ(inlined_frames[1]->source_line, 32); 457 ASSERT_EQ(inlined_frames[1]->source_line_base, 0x161b6U); 458 ASSERT_EQ(inlined_frames[1]->trust, StackFrame::FRAME_TRUST_INLINE); 459 460 ASSERT_EQ(inlined_frames[0]->function_name, "func()"); 461 ASSERT_EQ(inlined_frames[0]->function_base, 0x15b83U); 462 ASSERT_EQ(inlined_frames[0]->source_file_name, "linux_inline.cpp"); 463 ASSERT_EQ(inlined_frames[0]->source_line, 27); 464 ASSERT_EQ(inlined_frames[0]->source_line_base, 0x161b6U); 465 ASSERT_EQ(inlined_frames[0]->trust, StackFrame::FRAME_TRUST_INLINE); 466 } 467 468 TEST_F(TestBasicSourceLineResolver, TestLoadAndResolveNewInlines) { 469 TestCodeModule module("linux_inline"); 470 ASSERT_TRUE(resolver.LoadModule( 471 &module, testdata_dir + 472 "/symbols/linux_inline/BBA6FA10B8AAB33D00000000000000000/" 473 "linux_inline.new.sym")); 474 ASSERT_TRUE(resolver.HasModule(&module)); 475 StackFrame frame; 476 std::deque<std::unique_ptr<StackFrame>> inlined_frames; 477 frame.instruction = 0x161b6; 478 frame.module = &module; 479 // main frame. 480 resolver.FillSourceLineInfo(&frame, &inlined_frames); 481 ASSERT_EQ(frame.function_name, "main"); 482 ASSERT_EQ(frame.function_base, 0x15b30U); 483 ASSERT_EQ(frame.source_file_name, "a.cpp"); 484 ASSERT_EQ(frame.source_line, 42); 485 ASSERT_EQ(frame.source_line_base, 0x161b6U); 486 EXPECT_EQ(frame.is_multiple, false); 487 488 ASSERT_EQ(inlined_frames.size(), 3UL); 489 490 // Inlined frames inside main frame. 491 ASSERT_EQ(inlined_frames[2]->function_name, "foo()"); 492 ASSERT_EQ(inlined_frames[2]->function_base, 0x15b45U); 493 ASSERT_EQ(inlined_frames[2]->source_file_name, "b.cpp"); 494 ASSERT_EQ(inlined_frames[2]->source_line, 39); 495 ASSERT_EQ(inlined_frames[2]->source_line_base, 0x161b6U); 496 ASSERT_EQ(inlined_frames[2]->trust, StackFrame::FRAME_TRUST_INLINE); 497 498 ASSERT_EQ(inlined_frames[1]->function_name, "bar()"); 499 ASSERT_EQ(inlined_frames[1]->function_base, 0x15b72U); 500 ASSERT_EQ(inlined_frames[1]->source_file_name, "c.cpp"); 501 ASSERT_EQ(inlined_frames[1]->source_line, 32); 502 ASSERT_EQ(inlined_frames[1]->source_line_base, 0x161b6U); 503 ASSERT_EQ(inlined_frames[1]->trust, StackFrame::FRAME_TRUST_INLINE); 504 505 ASSERT_EQ(inlined_frames[0]->function_name, "func()"); 506 ASSERT_EQ(inlined_frames[0]->function_base, 0x15b83U); 507 ASSERT_EQ(inlined_frames[0]->source_file_name, "linux_inline.cpp"); 508 ASSERT_EQ(inlined_frames[0]->source_line, 27); 509 ASSERT_EQ(inlined_frames[0]->source_line_base, 0x161b6U); 510 ASSERT_EQ(inlined_frames[0]->trust, StackFrame::FRAME_TRUST_INLINE); 511 } 512 513 // Test parsing of valid FILE lines. The format is: 514 // FILE <id> <filename> 515 TEST(SymbolParseHelper, ParseFileValid) { 516 long index; 517 char* filename; 518 519 char kTestLine[] = "FILE 1 file name"; 520 ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename)); 521 EXPECT_EQ(1, index); 522 EXPECT_EQ("file name", string(filename)); 523 524 // 0 is a valid index. 525 char kTestLine1[] = "FILE 0 file name"; 526 ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename)); 527 EXPECT_EQ(0, index); 528 EXPECT_EQ("file name", string(filename)); 529 } 530 531 // Test parsing of invalid FILE lines. The format is: 532 // FILE <id> <filename> 533 TEST(SymbolParseHelper, ParseFileInvalid) { 534 long index; 535 char* filename; 536 537 // Test missing file name. 538 char kTestLine[] = "FILE 1 "; 539 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename)); 540 541 // Test bad index. 542 char kTestLine1[] = "FILE x1 file name"; 543 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename)); 544 545 // Test large index. 546 char kTestLine2[] = "FILE 123123123123123123123123 file name"; 547 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine2, &index, &filename)); 548 549 // Test negative index. 550 char kTestLine3[] = "FILE -2 file name"; 551 ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine3, &index, &filename)); 552 } 553 554 // Test parsing of valid FUNC lines. The format is: 555 // FUNC [<multiple>] <address> <size> <stack_param_size> <name> 556 TEST(SymbolParseHelper, ParseFunctionValid) { 557 bool multiple; 558 uint64_t address; 559 uint64_t size; 560 long stack_param_size; 561 char* name; 562 563 char kTestLine[] = "FUNC 1 2 3 function name"; 564 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine, &multiple, &address, 565 &size, &stack_param_size, 566 &name)); 567 EXPECT_FALSE(multiple); 568 EXPECT_EQ(1ULL, address); 569 EXPECT_EQ(2ULL, size); 570 EXPECT_EQ(3, stack_param_size); 571 EXPECT_EQ("function name", string(name)); 572 573 // Test hex address, size, and param size. 574 char kTestLine1[] = "FUNC a1 a2 a3 function name"; 575 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine1, &multiple, &address, 576 &size, &stack_param_size, 577 &name)); 578 EXPECT_FALSE(multiple); 579 EXPECT_EQ(0xa1ULL, address); 580 EXPECT_EQ(0xa2ULL, size); 581 EXPECT_EQ(0xa3, stack_param_size); 582 EXPECT_EQ("function name", string(name)); 583 584 char kTestLine2[] = "FUNC 0 0 0 function name"; 585 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine2, &multiple, &address, 586 &size, &stack_param_size, 587 &name)); 588 EXPECT_FALSE(multiple); 589 EXPECT_EQ(0ULL, address); 590 EXPECT_EQ(0ULL, size); 591 EXPECT_EQ(0, stack_param_size); 592 EXPECT_EQ("function name", string(name)); 593 594 // Test optional multiple field. 595 char kTestLine3[] = "FUNC m a1 a2 a3 function name"; 596 ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine3, &multiple, &address, 597 &size, &stack_param_size, 598 &name)); 599 EXPECT_TRUE(multiple); 600 EXPECT_EQ(0xa1ULL, address); 601 EXPECT_EQ(0xa2ULL, size); 602 EXPECT_EQ(0xa3, stack_param_size); 603 EXPECT_EQ("function name", string(name)); 604 } 605 606 // Test parsing of invalid FUNC lines. The format is: 607 // FUNC [<multiple>] <address> <size> <stack_param_size> <name> 608 TEST(SymbolParseHelper, ParseFunctionInvalid) { 609 bool multiple; 610 uint64_t address; 611 uint64_t size; 612 long stack_param_size; 613 char* name; 614 615 // Test missing function name. 616 char kTestLine[] = "FUNC 1 2 3 "; 617 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine, &multiple, &address, 618 &size, &stack_param_size, 619 &name)); 620 // Test bad address. 621 char kTestLine1[] = "FUNC 1z 2 3 function name"; 622 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine1, &multiple, &address, 623 &size, &stack_param_size, 624 &name)); 625 // Test large address. 626 char kTestLine2[] = "FUNC 123123123123123123123123123 2 3 function name"; 627 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine2, &multiple, &address, 628 &size, &stack_param_size, 629 &name)); 630 // Test bad size. 631 char kTestLine3[] = "FUNC 1 z2 3 function name"; 632 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine3, &multiple, &address, 633 &size, &stack_param_size, 634 &name)); 635 // Test large size. 636 char kTestLine4[] = "FUNC 1 231231231231231231231231232 3 function name"; 637 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine4, &multiple, &address, 638 &size, &stack_param_size, 639 &name)); 640 // Test bad param size. 641 char kTestLine5[] = "FUNC 1 2 3z function name"; 642 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine5, &multiple, &address, 643 &size, &stack_param_size, 644 &name)); 645 // Test large param size. 646 char kTestLine6[] = "FUNC 1 2 312312312312312312312312323 function name"; 647 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine6, &multiple, &address, 648 &size, &stack_param_size, 649 &name)); 650 // Negative param size. 651 char kTestLine7[] = "FUNC 1 2 -5 function name"; 652 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine7, &multiple, &address, 653 &size, &stack_param_size, 654 &name)); 655 // Test invalid optional field. 656 char kTestLine8[] = "FUNC x 1 2 5 function name"; 657 ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine8, &multiple, &address, 658 &size, &stack_param_size, 659 &name)); 660 } 661 662 // Test parsing of valid lines. The format is: 663 // <address> <size> <line number> <source file id> 664 TEST(SymbolParseHelper, ParseLineValid) { 665 uint64_t address; 666 uint64_t size; 667 long line_number; 668 long source_file; 669 670 char kTestLine[] = "1 2 3 4"; 671 ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine, &address, &size, 672 &line_number, &source_file)); 673 EXPECT_EQ(1ULL, address); 674 EXPECT_EQ(2ULL, size); 675 EXPECT_EQ(3, line_number); 676 EXPECT_EQ(4, source_file); 677 678 // Test hex size and address. 679 char kTestLine1[] = "a1 a2 3 4 // some comment"; 680 ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size, 681 &line_number, &source_file)); 682 EXPECT_EQ(0xa1ULL, address); 683 EXPECT_EQ(0xa2ULL, size); 684 EXPECT_EQ(3, line_number); 685 EXPECT_EQ(4, source_file); 686 687 // 0 is a valid line number. 688 char kTestLine2[] = "a1 a2 0 4 // some comment"; 689 ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size, 690 &line_number, &source_file)); 691 EXPECT_EQ(0xa1ULL, address); 692 EXPECT_EQ(0xa2ULL, size); 693 EXPECT_EQ(0, line_number); 694 EXPECT_EQ(4, source_file); 695 } 696 697 // Test parsing of invalid lines. The format is: 698 // <address> <size> <line number> <source file id> 699 TEST(SymbolParseHelper, ParseLineInvalid) { 700 uint64_t address; 701 uint64_t size; 702 long line_number; 703 long source_file; 704 705 // Test missing source file id. 706 char kTestLine[] = "1 2 3"; 707 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine, &address, &size, 708 &line_number, &source_file)); 709 // Test bad address. 710 char kTestLine1[] = "1z 2 3 4"; 711 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size, 712 &line_number, &source_file)); 713 // Test large address. 714 char kTestLine2[] = "123123123123123123123123 2 3 4"; 715 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size, 716 &line_number, &source_file)); 717 // Test bad size. 718 char kTestLine3[] = "1 z2 3 4"; 719 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine3, &address, &size, 720 &line_number, &source_file)); 721 // Test large size. 722 char kTestLine4[] = "1 123123123123123123123123 3 4"; 723 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine4, &address, &size, 724 &line_number, &source_file)); 725 // Test bad line number. 726 char kTestLine5[] = "1 2 z3 4"; 727 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine5, &address, &size, 728 &line_number, &source_file)); 729 // Test negative line number. 730 char kTestLine6[] = "1 2 -1 4"; 731 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine6, &address, &size, 732 &line_number, &source_file)); 733 // Test large line number. 734 char kTestLine7[] = "1 2 123123123123123123123 4"; 735 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine7, &address, &size, 736 &line_number, &source_file)); 737 // Test bad source file id. 738 char kTestLine8[] = "1 2 3 f"; 739 ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine8, &address, &size, 740 &line_number, &source_file)); 741 } 742 743 // Test parsing of valid PUBLIC lines. The format is: 744 // PUBLIC [<multiple>] <address> <stack_param_size> <name> 745 TEST(SymbolParseHelper, ParsePublicSymbolValid) { 746 bool multiple; 747 uint64_t address; 748 long stack_param_size; 749 char* name; 750 751 char kTestLine[] = "PUBLIC 1 2 3"; 752 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &multiple, 753 &address, &stack_param_size, 754 &name)); 755 EXPECT_FALSE(multiple); 756 EXPECT_EQ(1ULL, address); 757 EXPECT_EQ(2, stack_param_size); 758 EXPECT_EQ("3", string(name)); 759 760 // Test hex size and address. 761 char kTestLine1[] = "PUBLIC a1 a2 function name"; 762 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &multiple, 763 &address, &stack_param_size, 764 &name)); 765 EXPECT_FALSE(multiple); 766 EXPECT_EQ(0xa1ULL, address); 767 EXPECT_EQ(0xa2, stack_param_size); 768 EXPECT_EQ("function name", string(name)); 769 770 // Test 0 is a valid address. 771 char kTestLine2[] = "PUBLIC 0 a2 function name"; 772 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &multiple, 773 &address, &stack_param_size, 774 &name)); 775 EXPECT_FALSE(multiple); 776 EXPECT_EQ(0ULL, address); 777 EXPECT_EQ(0xa2, stack_param_size); 778 EXPECT_EQ("function name", string(name)); 779 780 // Test optional multiple field. 781 char kTestLine3[] = "PUBLIC m a1 a2 function name"; 782 ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &multiple, 783 &address, &stack_param_size, 784 &name)); 785 EXPECT_TRUE(multiple); 786 EXPECT_EQ(0xa1ULL, address); 787 EXPECT_EQ(0xa2, stack_param_size); 788 EXPECT_EQ("function name", string(name)); 789 } 790 791 // Test parsing of invalid PUBLIC lines. The format is: 792 // PUBLIC [<multiple>] <address> <stack_param_size> <name> 793 TEST(SymbolParseHelper, ParsePublicSymbolInvalid) { 794 bool multiple; 795 uint64_t address; 796 long stack_param_size; 797 char* name; 798 799 // Test missing source function name. 800 char kTestLine[] = "PUBLIC 1 2 "; 801 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &multiple, 802 &address, &stack_param_size, 803 &name)); 804 // Test bad address. 805 char kTestLine1[] = "PUBLIC 1z 2 3"; 806 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &multiple, 807 &address, &stack_param_size, 808 &name)); 809 // Test large address. 810 char kTestLine2[] = "PUBLIC 123123123123123123123123 2 3"; 811 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &multiple, 812 &address, &stack_param_size, 813 &name)); 814 // Test bad param stack size. 815 char kTestLine3[] = "PUBLIC 1 z2 3"; 816 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &multiple, 817 &address, &stack_param_size, 818 &name)); 819 // Test large param stack size. 820 char kTestLine4[] = "PUBLIC 1 123123123123123123123123123 3"; 821 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine4, &multiple, 822 &address, &stack_param_size, 823 &name)); 824 // Test negative param stack size. 825 char kTestLine5[] = "PUBLIC 1 -5 3"; 826 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine5, &multiple, 827 &address, &stack_param_size, 828 &name)); 829 // Test invalid optional field. 830 char kTestLine6[] = "PUBLIC x 1 5 3"; 831 ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine6, &multiple, 832 &address, &stack_param_size, 833 &name)); 834 } 835 836 // Test parsing of valid INLINE_ORIGIN lines. 837 // The old format: 838 // INLINE_ORIGIN <origin_id> <file_id> <name> 839 // The new format: 840 // INLINE_ORIGIN <origin_id> <name> 841 TEST(SymbolParseHelper, ParseInlineOriginValid) { 842 bool has_file_id; 843 long origin_id; 844 long file_id; 845 char* name; 846 // Test for old format. 847 char kTestLine[] = "INLINE_ORIGIN 1 1 function name"; 848 ASSERT_TRUE(SymbolParseHelper::ParseInlineOrigin( 849 kTestLine, &has_file_id, &origin_id, &file_id, &name)); 850 EXPECT_EQ(true, has_file_id); 851 EXPECT_EQ(1, origin_id); 852 EXPECT_EQ(1, file_id); 853 EXPECT_EQ("function name", string(name)); 854 855 // -1 is a file id, which is used when the function is artifical. 856 char kTestLine1[] = "INLINE_ORIGIN 0 -1 function name"; 857 ASSERT_TRUE(SymbolParseHelper::ParseInlineOrigin( 858 kTestLine1, &has_file_id, &origin_id, &file_id, &name)); 859 EXPECT_EQ(true, has_file_id); 860 EXPECT_EQ(0, origin_id); 861 EXPECT_EQ(-1, file_id); 862 EXPECT_EQ("function name", string(name)); 863 864 // Test for new format. 865 char kTestLine2[] = "INLINE_ORIGIN 0 function name"; 866 ASSERT_TRUE(SymbolParseHelper::ParseInlineOrigin( 867 kTestLine2, &has_file_id, &origin_id, &file_id, &name)); 868 EXPECT_EQ(false, has_file_id); 869 EXPECT_EQ(0, origin_id); 870 EXPECT_EQ("function name", string(name)); 871 872 char kTestLine3[] = "INLINE_ORIGIN 0 function"; 873 ASSERT_TRUE(SymbolParseHelper::ParseInlineOrigin( 874 kTestLine3, &has_file_id, &origin_id, &file_id, &name)); 875 EXPECT_EQ(false, has_file_id); 876 EXPECT_EQ(0, origin_id); 877 EXPECT_EQ("function", string(name)); 878 } 879 880 // Test parsing of valid INLINE ORIGIN lines. The format is: 881 // INLINE_ORIGIN <origin_id> <file_id> <name> 882 TEST(SymbolParseHelper, ParseInlineOriginInvalid) { 883 bool has_file_id; 884 long origin_id; 885 long file_id; 886 char* name; 887 888 // Test missing function name. 889 char kTestLine[] = "INLINE_ORIGIN 1 1"; 890 ASSERT_FALSE(SymbolParseHelper::ParseInlineOrigin( 891 kTestLine, &has_file_id, &origin_id, &file_id, &name)); 892 893 // Test bad origin id. 894 char kTestLine1[] = "INLINE_ORIGIN x1 1 function name"; 895 ASSERT_FALSE(SymbolParseHelper::ParseInlineOrigin( 896 kTestLine1, &has_file_id, &origin_id, &file_id, &name)); 897 898 // Test large origin id. 899 char kTestLine2[] = "INLINE_ORIGIN 123123123123123123123123 1 function name"; 900 ASSERT_FALSE(SymbolParseHelper::ParseInlineOrigin( 901 kTestLine2, &has_file_id, &origin_id, &file_id, &name)); 902 903 // Test negative origin id. 904 char kTestLine3[] = "INLINE_ORIGIN -1 1 function name"; 905 ASSERT_FALSE(SymbolParseHelper::ParseInlineOrigin( 906 kTestLine3, &has_file_id, &origin_id, &file_id, &name)); 907 } 908 909 // Test parsing of valid INLINE lines. 910 // The old format: 911 // INLINE <inline_nest_level> <call_site_line> <origin_id> [<address> <size>]+ 912 // The new format: 913 // INLINE <inline_nest_level> <call_site_line> <call_site_file_id> <origin_id> 914 // [<address> <size>]+ 915 TEST(SymbolParseHelper, ParseInlineValid) { 916 bool has_call_site_file_id; 917 long inline_nest_level; 918 long call_site_line; 919 long call_site_file_id; 920 long origin_id; 921 std::vector<std::pair<uint64_t, uint64_t>> ranges; 922 923 // Test for old format. 924 char kTestLine[] = "INLINE 0 1 2 3 4"; 925 ASSERT_TRUE(SymbolParseHelper::ParseInline( 926 kTestLine, &has_call_site_file_id, &inline_nest_level, &call_site_line, 927 &call_site_file_id, &origin_id, &ranges)); 928 EXPECT_EQ(false, has_call_site_file_id); 929 EXPECT_EQ(0, inline_nest_level); 930 EXPECT_EQ(1, call_site_line); 931 EXPECT_EQ(2, origin_id); 932 EXPECT_EQ(0x3ULL, ranges[0].first); 933 EXPECT_EQ(0x4ULL, ranges[0].second); 934 ranges.clear(); 935 936 // Test hex and discontinuous ranges. 937 char kTestLine1[] = "INLINE 0 1 2 a b 1a 1b"; 938 ASSERT_TRUE(SymbolParseHelper::ParseInline( 939 kTestLine1, &has_call_site_file_id, &inline_nest_level, &call_site_line, 940 &call_site_file_id, &origin_id, &ranges)); 941 EXPECT_EQ(false, has_call_site_file_id); 942 EXPECT_EQ(0, inline_nest_level); 943 EXPECT_EQ(1, call_site_line); 944 EXPECT_EQ(2, origin_id); 945 EXPECT_EQ(0xaULL, ranges[0].first); 946 EXPECT_EQ(0xbULL, ranges[0].second); 947 EXPECT_EQ(0x1aULL, ranges[1].first); 948 EXPECT_EQ(0x1bULL, ranges[1].second); 949 950 // Test for new format. 951 char kTestLine2[] = "INLINE 0 1 2 3 a b 1a 1b"; 952 ASSERT_TRUE(SymbolParseHelper::ParseInline( 953 kTestLine2, &has_call_site_file_id, &inline_nest_level, &call_site_line, 954 &call_site_file_id, &origin_id, &ranges)); 955 EXPECT_EQ(true, has_call_site_file_id); 956 EXPECT_EQ(0, inline_nest_level); 957 EXPECT_EQ(1, call_site_line); 958 EXPECT_EQ(2, call_site_file_id); 959 EXPECT_EQ(3, origin_id); 960 EXPECT_EQ(0xaULL, ranges[0].first); 961 EXPECT_EQ(0xbULL, ranges[0].second); 962 EXPECT_EQ(0x1aULL, ranges[1].first); 963 EXPECT_EQ(0x1bULL, ranges[1].second); 964 } 965 966 // Test parsing of Invalid INLINE lines. 967 TEST(SymbolParseHelper, ParseInlineInvalid) { 968 bool has_call_site_file_id; 969 long inline_nest_level; 970 long call_site_line; 971 long call_site_file_id; 972 long origin_id; 973 std::vector<std::pair<uint64_t, uint64_t>> ranges; 974 975 // Test negative inline_nest_level. 976 char kTestLine[] = "INLINE -1 1 2 3 4"; 977 ASSERT_FALSE(SymbolParseHelper::ParseInline( 978 kTestLine, &has_call_site_file_id, &inline_nest_level, &call_site_line, 979 &call_site_file_id, &origin_id, &ranges)); 980 981 // Test negative call_site_line. 982 char kTestLine1[] = "INLINE 0 -1 2 3 4"; 983 ASSERT_FALSE(SymbolParseHelper::ParseInline( 984 kTestLine1, &has_call_site_file_id, &inline_nest_level, &call_site_line, 985 &call_site_file_id, &origin_id, &ranges)); 986 987 // Test negative origin_id. 988 char kTestLine2[] = "INLINE 0 1 -2 3 4"; 989 ASSERT_FALSE(SymbolParseHelper::ParseInline( 990 kTestLine2, &has_call_site_file_id, &inline_nest_level, &call_site_line, 991 &call_site_file_id, &origin_id, &ranges)); 992 993 // Test missing ranges. 994 char kTestLine3[] = "INLINE 0 1 -2"; 995 ASSERT_FALSE(SymbolParseHelper::ParseInline( 996 kTestLine3, &has_call_site_file_id, &inline_nest_level, &call_site_line, 997 &call_site_file_id, &origin_id, &ranges)); 998 999 // Test missing size for range. 1000 char kTestLine4[] = "INLINE 0 1 -2 3"; 1001 ASSERT_FALSE(SymbolParseHelper::ParseInline( 1002 kTestLine4, &has_call_site_file_id, &inline_nest_level, &call_site_line, 1003 &call_site_file_id, &origin_id, &ranges)); 1004 } 1005 1006 } // namespace 1007 1008 int main(int argc, char* argv[]) { 1009 ::testing::InitGoogleTest(&argc, argv); 1010 return RUN_ALL_TESTS(); 1011 }