• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
TestCodeModule(string code_file)63   TestCodeModule(string code_file) : code_file_(code_file) {}
~TestCodeModule()64   virtual ~TestCodeModule() {}
65 
base_address() const66   virtual uint64_t base_address() const { return 0; }
size() const67   virtual uint64_t size() const { return 0xb000; }
code_file() const68   virtual string code_file() const { return code_file_; }
code_identifier() const69   virtual string code_identifier() const { return ""; }
debug_file() const70   virtual string debug_file() const { return ""; }
debug_identifier() const71   virtual string debug_identifier() const { return ""; }
version() const72   virtual string version() const { return ""; }
Copy() const73   virtual CodeModule* Copy() const {
74     return new TestCodeModule(code_file_);
75   }
is_unloaded() const76   virtual bool is_unloaded() const { return false; }
shrink_down_delta() const77   virtual uint64_t shrink_down_delta() const { return 0; }
SetShrinkDownDelta(uint64_t shrink_down_delta)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 {
GetBase() const86   uint64_t GetBase() const { return 0x10000; }
GetSize() const87   uint32_t GetSize() const { return 0x01000; }
GetMemoryAtAddress(uint64_t address,uint8_t * value) const88   bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const {
89     *value = address & 0xff;
90     return true;
91   }
GetMemoryAtAddress(uint64_t address,uint16_t * value) const92   bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const {
93     *value = address & 0xffff;
94     return true;
95   }
GetMemoryAtAddress(uint64_t address,uint32_t * value) const96   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   }
GetMemoryAtAddress(uint64_t address,uint64_t * value) const107   bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const {
108     *value = address;
109     return true;
110   }
Print() const111   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".
VerifyRegisters(const char * file,int line,const CFIFrameInfo::RegisterValueMap<uint32_t> & expected,const CFIFrameInfo::RegisterValueMap<uint32_t> & actual)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 
VerifyEmpty(const StackFrame & frame)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 
ClearSourceLineInfo(StackFrame * frame)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:
SetUp()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 
TEST_F(TestBasicSourceLineResolver,TestLoadAndResolve)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 
TEST_F(TestBasicSourceLineResolver,TestInvalidLoads)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 
TEST_F(TestBasicSourceLineResolver,TestUnload)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 
TEST_F(TestBasicSourceLineResolver,TestLoadAndResolveOldInlines)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 
TEST_F(TestBasicSourceLineResolver,TestLoadAndResolveNewInlines)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>
TEST(SymbolParseHelper,ParseFileValid)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>
TEST(SymbolParseHelper,ParseFileInvalid)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>
TEST(SymbolParseHelper,ParseFunctionValid)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>
TEST(SymbolParseHelper,ParseFunctionInvalid)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>
TEST(SymbolParseHelper,ParseLineValid)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>
TEST(SymbolParseHelper,ParseLineInvalid)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>
TEST(SymbolParseHelper,ParsePublicSymbolValid)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>
TEST(SymbolParseHelper,ParsePublicSymbolInvalid)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>
TEST(SymbolParseHelper,ParseInlineOriginValid)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>
TEST(SymbolParseHelper,ParseInlineOriginInvalid)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>]+
TEST(SymbolParseHelper,ParseInlineValid)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.
TEST(SymbolParseHelper,ParseInlineInvalid)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 
main(int argc,char * argv[])1008 int main(int argc, char* argv[]) {
1009   ::testing::InitGoogleTest(&argc, argv);
1010   return RUN_ALL_TESTS();
1011 }
1012