• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "test/gtest_and_gmock.h"
18 
19 #include "perfetto/ext/base/file_utils.h"
20 #include "perfetto/ext/base/temp_file.h"
21 #include "src/profiling/symbolizer/breakpad_parser.h"
22 
23 namespace perfetto {
24 namespace profiling {
25 
26 namespace {
27 
28 // Used to initialize parser objects.
29 constexpr char kFakeFilePath[] = "bad/file/path";
30 
TEST(BreakpadParserTest,FileIsEmpty)31 TEST(BreakpadParserTest, FileIsEmpty) {
32   base::TempFile file = base::TempFile::Create();
33   BreakpadParser parser(file.path());
34   ASSERT_TRUE(parser.ParseFile());
35   EXPECT_TRUE(parser.symbols_for_testing().empty());
36 }
37 
TEST(BreakpadParserTest,FileNotOpened)38 TEST(BreakpadParserTest, FileNotOpened) {
39   BreakpadParser parser(kFakeFilePath);
40   ASSERT_FALSE(parser.ParseFile());
41   EXPECT_TRUE(parser.symbols_for_testing().empty());
42 }
43 
TEST(BreakpadParserTest,ContainsNoFuncRecord)44 TEST(BreakpadParserTest, ContainsNoFuncRecord) {
45   BreakpadParser parser(kFakeFilePath);
46   constexpr char kTestFileContents[] =
47       "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
48       "FILE 0 /Applications/../MacOSX10.10.sdk/usr/include/ctype.h\n"
49       "1031 2 39 4\n"
50       "STACK CFI 1014 .cfa: $rbp 16 +\n";
51   ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
52   EXPECT_TRUE(parser.symbols_for_testing().empty());
53   EXPECT_TRUE(parser.public_symbols_for_testing().empty());
54 }
55 
TEST(BreakpadParserTest,ContainsOneFuncRecord)56 TEST(BreakpadParserTest, ContainsOneFuncRecord) {
57   BreakpadParser parser(kFakeFilePath);
58   constexpr char kTestFileContents[] =
59       "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
60       "FUNC 1010 23 0 foo::bar()\n"
61       "1031 2 39 4\n"
62       "PUBLIC 2e7c0 0 items\n";
63   ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
64   ASSERT_EQ(parser.symbols_for_testing().size(), 1u);
65   ASSERT_EQ(parser.public_symbols_for_testing().size(), 1u);
66   EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(),
67                "foo::bar()");
68   EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
69             static_cast<uint64_t>(0x1010));
70 }
71 
TEST(BreakpadParserTest,ContainsManyFuncRecords)72 TEST(BreakpadParserTest, ContainsManyFuncRecords) {
73   BreakpadParser parser(kFakeFilePath);
74   constexpr char kTestFileContents[] =
75       "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
76       "FUNC 1010 23 0 foo_foo\n"
77       "1031 2 39 4\n"
78       "FUNC 1040 84 0 bar_1\n"
79       "1040 4 44 5\n"
80       "FUNC 10d0 6b 0 baz_baz()\n";
81   ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
82   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
83   EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(), "foo_foo");
84   EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
85             static_cast<uint64_t>(0x1010));
86   EXPECT_EQ(parser.symbols_for_testing()[0].function_size, 35u);
87   EXPECT_STREQ(parser.symbols_for_testing()[1].symbol_name.c_str(), "bar_1");
88   EXPECT_EQ(parser.symbols_for_testing()[1].start_address,
89             static_cast<uint64_t>(0x1040));
90   EXPECT_EQ(parser.symbols_for_testing()[1].function_size, 132u);
91   EXPECT_STREQ(parser.symbols_for_testing()[2].symbol_name.c_str(),
92                "baz_baz()");
93   EXPECT_EQ(parser.symbols_for_testing()[2].start_address,
94             static_cast<uint64_t>(0x10d0));
95   EXPECT_EQ(parser.symbols_for_testing()[2].function_size, 107u);
96 }
97 
TEST(BreakpadParserTest,OptionalArgument)98 TEST(BreakpadParserTest, OptionalArgument) {
99   BreakpadParser parser(kFakeFilePath);
100   constexpr char kTestFileContents[] =
101       "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
102       "FUNC m 1010 23 0 foo_foo()\n"
103       "1031 2 39 4\n"
104       "FUNC m 1040 84 0 bar_1\n";
105   ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
106   ASSERT_EQ(parser.symbols_for_testing().size(), 2u);
107   EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(),
108                "foo_foo()");
109   EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
110             static_cast<uint64_t>(0x1010));
111   EXPECT_STREQ(parser.symbols_for_testing()[1].symbol_name.c_str(), "bar_1");
112   EXPECT_EQ(parser.symbols_for_testing()[1].start_address,
113             static_cast<uint64_t>(0x1040));
114 }
115 
TEST(BreakpadParserTest,FuncNameWithSpaces)116 TEST(BreakpadParserTest, FuncNameWithSpaces) {
117   BreakpadParser parser(kFakeFilePath);
118   constexpr char kTestFileContents[] =
119       "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
120       "FUNC 1010 23 0 foo foo foo\n"
121       "1031 2 39 4\n"
122       "FUNC 1040 84 0 bar\n"
123       "1040 4 44 5\n"
124       "FUNC 10d0 6b 0 baz\n";
125   ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
126   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
127   EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(),
128                "foo foo foo");
129   EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
130             static_cast<uint64_t>(0x1010));
131   EXPECT_STREQ(parser.symbols_for_testing()[2].symbol_name.c_str(), "baz");
132   EXPECT_EQ(parser.symbols_for_testing()[2].start_address,
133             static_cast<uint64_t>(0x10d0));
134 }
135 
TEST(BreakpadParserTest,NonHexAddress)136 TEST(BreakpadParserTest, NonHexAddress) {
137   BreakpadParser parser(kFakeFilePath);
138   constexpr char kTestFileContents[] =
139       "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
140       "FUNC foo 23 0 foo\n"
141       "1031 2 39 4\n"
142       "FUNC 1040 84 0 bar\n"
143       "1040 4 44 5\n"
144       "FUNC 10d0 6b 0 baz\n";
145   ASSERT_FALSE(parser.ParseFromString(kTestFileContents));
146   EXPECT_TRUE(parser.symbols_for_testing().empty());
147 }
148 
TEST(BreakpadParserTest,NoModuleRecord)149 TEST(BreakpadParserTest, NoModuleRecord) {
150   BreakpadParser parser(kFakeFilePath);
151   constexpr char kTestFileContents[] =
152       "FUNC foo 23 0 foo()\n"
153       "1031 2 39 4\n"
154       "FUNC 1040 84 0 bar\n"
155       "1040 4 44 5\n"
156       "FUNC 10d0 6b 0 baz\n";
157   ASSERT_FALSE(parser.ParseFromString(kTestFileContents));
158   EXPECT_TRUE(parser.symbols_for_testing().empty());
159 }
160 
161 // To make it easy to read, each FUNC record is followed by two LINE records:
162 // one showing the start address of the ending instruction and one showing the
163 // address where the function ends.
164 constexpr char kGetSymbolTestContents[] =
165     "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
166     "FUNC 1010 23 0 foo\n"
167     "1031 2 39 4\n"
168     "1033 0 0 0\n"
169     "FUNC 1040 84 0 bar\n"
170     "10b6 e 44 5\n"
171     "10c4 0 0 0\n"
172     "FUNC 10d0 6b 0 baz\n"
173     "1136 5 44 5\n"
174     "113b 0 0 0\n"
175     "PUBLIC 12010 0 p_foo\n"
176     "PUBLIC 12018 0 p_bar\n"
177     "PUBLIC 12050 0 p_bax\n"
178     "PUBLIC 12090 0 p_baz\n";
179 
TEST(BreakpadParserTest,GivenStartAddr)180 TEST(BreakpadParserTest, GivenStartAddr) {
181   BreakpadParser parser(kFakeFilePath);
182   ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
183   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
184   EXPECT_EQ(*parser.GetSymbol(0x1010U), "foo");
185   EXPECT_EQ(*parser.GetSymbol(0x10d0U), "baz");
186 
187   ASSERT_EQ(parser.public_symbols_for_testing().size(), 4u);
188   EXPECT_EQ(*parser.GetPublicSymbol(0x12010U), "p_foo");
189   EXPECT_EQ(*parser.GetPublicSymbol(0x12018U), "p_bar");
190   EXPECT_EQ(*parser.GetPublicSymbol(0x12050U), "p_bax");
191   EXPECT_FALSE(parser.GetPublicSymbol(0x12090U));
192 }
193 
TEST(BreakpadParserTest,GivenAddrInRange)194 TEST(BreakpadParserTest, GivenAddrInRange) {
195   BreakpadParser parser(kFakeFilePath);
196   ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
197   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
198   EXPECT_EQ(*parser.GetSymbol(0x1030U), "foo");
199   EXPECT_EQ(*parser.GetSymbol(0x10c0U), "bar");
200 
201   ASSERT_EQ(parser.public_symbols_for_testing().size(), 4u);
202   EXPECT_EQ(*parser.GetPublicSymbol(0x12014U), "p_foo");
203   EXPECT_EQ(*parser.GetPublicSymbol(0x12038U), "p_bar");
204   EXPECT_EQ(*parser.GetPublicSymbol(0x12068U), "p_bax");
205 }
206 
TEST(BreakpadParserTest,AddrTooLow)207 TEST(BreakpadParserTest, AddrTooLow) {
208   BreakpadParser parser(kFakeFilePath);
209   ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
210   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
211   EXPECT_FALSE(parser.GetSymbol(0x1000U));
212 
213   ASSERT_EQ(parser.public_symbols_for_testing().size(), 4u);
214   EXPECT_FALSE(parser.GetPublicSymbol(0x12000U));
215 }
216 
TEST(BreakpadParserTest,AddrTooHigh)217 TEST(BreakpadParserTest, AddrTooHigh) {
218   BreakpadParser parser(kFakeFilePath);
219   ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
220   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
221   EXPECT_FALSE(parser.GetSymbol(0x3000U));
222 
223   ASSERT_EQ(parser.public_symbols_for_testing().size(), 4u);
224   EXPECT_FALSE(parser.GetPublicSymbol(0x15000U));
225 }
226 
TEST(BreakpadParserTest,AddrBetweenFunctions)227 TEST(BreakpadParserTest, AddrBetweenFunctions) {
228   BreakpadParser parser(kFakeFilePath);
229   ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
230   ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
231   EXPECT_FALSE(parser.GetSymbol(0x1036U));
232 }
233 
234 }  // namespace
235 }  // namespace profiling
236 }  // namespace perfetto
237