/ src / processor / basic_source_line_resolver_unittest.cc
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  }