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