1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "symbols_file_test.h"
17
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 #include <hilog/log.h>
21 #include <random>
22 #include <unistd.h>
23
24 using namespace testing::ext;
25 using namespace std;
26 using namespace OHOS::HiviewDFX;
27
28 namespace OHOS {
29 namespace Developtools {
30 namespace HiPerf {
31 class SymbolsFileTest : public testing::Test {
32 public:
33 static void SetUpTestCase(void);
34 static void TearDownTestCase(void);
35 void SetUp();
36 void TearDown();
37 void CheckSymbols(const std::unique_ptr<SymbolsFile> &symbolsFile) const;
38 void PrintSymbols(const std::vector<Symbol> &symbol) const;
39 bool KptrRestrict() const;
40
LoadSymbols(SymbolsFileType symbolsFileType)41 std::unique_ptr<SymbolsFile> LoadSymbols(SymbolsFileType symbolsFileType)
42 {
43 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(symbolsFileType);
44 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
45 return symbolsFile;
46 }
47
TestLoadSymbols(SymbolsFileType symbolsFileType,const std::string & path)48 bool TestLoadSymbols(SymbolsFileType symbolsFileType, const std::string &path)
49 {
50 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(symbolsFileType);
51 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
52 return symbolsFile->LoadSymbols(path);
53 }
54 default_random_engine rnd_;
55 };
56
SetUpTestCase()57 void SymbolsFileTest::SetUpTestCase() {}
58
TearDownTestCase()59 void SymbolsFileTest::TearDownTestCase() {}
60
SetUp()61 void SymbolsFileTest::SetUp() {}
62
TearDown()63 void SymbolsFileTest::TearDown() {}
64
KptrRestrict() const65 bool SymbolsFileTest::KptrRestrict() const
66 {
67 std::ifstream inputString(KPTR_RESTRICT, std::ios::in);
68 if (inputString) {
69 string kptrRestrict = "1";
70 inputString >> kptrRestrict;
71 if (kptrRestrict == "0") {
72 return false;
73 }
74 }
75 return true;
76 }
77
CheckSymbols(const std::unique_ptr<SymbolsFile> & symbolsFile) const78 void SymbolsFileTest::CheckSymbols(const std::unique_ptr<SymbolsFile> &symbolsFile) const
79 {
80 auto symbols = symbolsFile->GetSymbols();
81 EXPECT_EQ(symbols.empty(), false);
82 ASSERT_GE(symbols.size(), 1u);
83 PrintSymbols(symbols);
84
85 // first is 0
86 EXPECT_EQ(symbolsFile->GetSymbolWithVaddr(0x0).funcVaddr_, 0u);
87
88 // last is isValid
89 EXPECT_EQ(symbolsFile->GetSymbolWithVaddr(std::numeric_limits<uint64_t>::max()).isValid(),
90 true);
91
92 for (uint64_t pos = 0; pos < symbols.size(); ++pos) {
93 uint64_t vaddr = symbols[pos].funcVaddr_;
94 EXPECT_EQ(symbolsFile->GetSymbolWithVaddr(vaddr).funcVaddr_, vaddr);
95 }
96 for (auto symbol : symbols) {
97 if (symbol.name_.find("_Z") != std::string::npos) {
98 EXPECT_NE(symbol.demangle_.find("_Z"), 0u);
99 }
100 }
101 }
102
PrintSymbols(const std::vector<Symbol> & symbols) const103 void SymbolsFileTest::PrintSymbols(const std::vector<Symbol> &symbols) const
104 {
105 size_t printNumber = 15;
106 if (printNumber > symbols.size())
107 printNumber = symbols.size();
108
109 printf("first %zu:\n", printNumber);
110 for (size_t i = 0; i < printNumber; i++) {
111 printf("%s\n", symbols[i].ToDebugString().c_str());
112 }
113 if (printNumber < symbols.size()) {
114 printf("last %zu:\n", printNumber);
115 for (size_t i = printNumber; i > 0; i--) {
116 printf("%s\n", symbols[symbols.size() - i].ToDebugString().c_str());
117 }
118 }
119 }
120
121 /**
122 * @tc.name: Symbol Name
123 * @tc.desc:
124 * @tc.type: FUNC
125 */
126 HWTEST_F(SymbolsFileTest, SymbolName, TestSize.Level1)
127 {
128 Symbol symbol1(0x1000);
129 EXPECT_STREQ(symbol1.Name().data(), "@0x1000");
130
131 Symbol symbol2(0x1001);
132 EXPECT_STREQ(symbol2.Name().data(), "@0x1001");
133
134 Symbol symbol3(0xFFF);
135 EXPECT_STREQ(symbol3.Name().data(), "@0xfff");
136 }
137
138 /**
139 * @tc.name: setSymbolsFilePath
140 * @tc.desc:
141 * @tc.type: FUNC
142 */
143 HWTEST_F(SymbolsFileTest, setSymbolsFilePath, TestSize.Level1)
144 {
145 auto symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
146 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_DATA_TEMP), true);
147 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_NOT_EXISTS), false);
148 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_DATA_TEMP_WINDOS), false);
149 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_ILLEGAL), false);
150 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
151 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA_NO_ENDPATH), true);
152 }
153
154 /**
155 * @tc.name: setSymbolsFilePath
156 * @tc.desc:
157 * @tc.type: FUNC
158 */
159 HWTEST_F(SymbolsFileTest, setSymbolsFilePathVectorSuccess, TestSize.Level1)
160 {
161 auto symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
162 std::vector<std::string> symbolsSearchPaths;
163
164 symbolsSearchPaths.clear();
165 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
166 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), true);
167
168 symbolsSearchPaths.clear();
169 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
170 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
171 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), true);
172
173 symbolsSearchPaths.clear();
174 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
175 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
176 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
177 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), true);
178 }
179
180 /**
181 * @tc.name: setSymbolsFilePath
182 * @tc.desc:
183 * @tc.type: FUNC
184 */
185 HWTEST_F(SymbolsFileTest, setSymbolsFilePathVectorFailed, TestSize.Level1)
186 {
187 auto symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
188 std::vector<std::string> symbolsSearchPaths;
189
190 symbolsSearchPaths.clear();
191 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
192 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), false);
193
194 symbolsSearchPaths.clear();
195 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
196 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
197 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), false);
198
199 symbolsSearchPaths.clear();
200 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
201 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
202 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
203 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), false);
204 }
205
206 /**
207 * @tc.name: setSymbolsFilePath
208 * @tc.desc:
209 * @tc.type: FUNC
210 */
211 HWTEST_F(SymbolsFileTest, setSymbolsFilePathVectorMixSucessed, TestSize.Level1)
212 {
213 auto symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
214 std::vector<std::string> symbolsSearchPaths;
215
216 symbolsSearchPaths.clear();
217 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
218 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
219 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), true);
220
221 symbolsSearchPaths.clear();
222 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
223 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
224 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
225 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
226 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), true);
227
228 symbolsSearchPaths.clear();
229 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
230 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
231 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
232 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
233 symbolsSearchPaths.push_back(PATH_DATA_TEMP);
234 symbolsSearchPaths.push_back(PATH_NOT_EXISTS);
235 EXPECT_EQ(symbolsFile->setSymbolsFilePath(symbolsSearchPaths), true);
236 }
237
TestLoadSymbols(SymbolsFileType symbolsFileType,const std::string & path)238 bool TestLoadSymbols(SymbolsFileType symbolsFileType, const std::string &path)
239 {
240 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(symbolsFileType);
241 EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
242 return symbolsFile->LoadSymbols(path);
243 }
244
245 /**
246 * @tc.name: SymbolsFile Default Virtual
247 * @tc.desc:
248 * @tc.type: FUNC
249 */
250 HWTEST_F(SymbolsFileTest, SymbolsFileDefaultVirtual, TestSize.Level1)
251 {
252 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
253 uint64_t value = 0;
254 uint8_t *ptr = nullptr;
255 ASSERT_EQ(symbolsFile->LoadDebugInfo(), false);
256 EXPECT_EQ(symbolsFile->ReadRoMemory(0, ptr, 0), false);
257 EXPECT_EQ(symbolsFile->GetSectionInfo("", value, value, value), false);
258 #ifndef __arm__
259 EXPECT_EQ(symbolsFile->GetHDRSectionInfo(value, value, value), false);
260 #endif
261 }
262
263 /**
264 * @tc.name: LoaderKernelSymbols
265 * @tc.desc:
266 * @tc.type: FUNC
267 */
268 HWTEST_F(SymbolsFileTest, LoadKernelSymbols, TestSize.Level1)
269 {
270 if (access("/sys/kernel/notes", F_OK) != 0) {
271 printf("cannot access /sys/kernel/notes\n");
272 return;
273 }
274 // read from kernel runtime
275 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE);
276 ScopeDebugLevel tempLogLevel(LEVEL_VERBOSE);
277 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
278
279 const std::vector<Symbol> &symbols = symbolsFile->GetSymbols();
280 EXPECT_EQ(symbols.empty(), false);
281
282 std::string modulesMap = ReadFileToString("/proc/modules");
283 int lines = std::count(modulesMap.begin(), modulesMap.end(), '\n');
284 if (lines < 0) {
285 return;
286 }
287 std::set<std::string> modulesCount;
288 for (auto &symbol : symbols) {
289 if (symbol.module_.length()) {
290 modulesCount.emplace(symbol.module_);
291 }
292 }
293
294 // add [kernel.kallsyms]
295 EXPECT_GE(modulesCount.size(), lines + 1u);
296 if (HasFailure()) {
297 for (auto &module : modulesCount) {
298 printf("%s\n", module.c_str());
299 }
300 }
301
302 // try vmlinux
303 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX), true);
304 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX_STRIPPED), true);
305 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX_STRIPPED_NOBUILDID), true);
306 // will be load from runtime, still return true
307 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX_STRIPPED_BROKEN), true);
308 }
309
310 /**
311 * @tc.name: LoaderElfSymbols
312 * @tc.desc:
313 * @tc.type: FUNC
314 */
315 HWTEST_F(SymbolsFileTest, LoadElfSymbols, TestSize.Level1)
316 {
317 auto symbolsElfLoader = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
318 auto symbolsElfStrippedLoader = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
319 ScopeDebugLevel tempLogLevel(LEVEL_VERBOSE);
320
321 EXPECT_EQ(symbolsElfLoader->LoadSymbols(), false);
322
323 ASSERT_EQ(symbolsElfLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
324 EXPECT_EQ(symbolsElfLoader->LoadSymbols(TEST_FILE_ELF), true);
325 if (HasFailure()) {
326 PrintSymbols(symbolsElfLoader->GetSymbols());
327 }
328
329 ASSERT_EQ(symbolsElfStrippedLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
330 EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(TEST_FILE_ELF_STRIPPED), true);
331 if (HasFailure()) {
332 PrintSymbols(symbolsElfStrippedLoader->GetSymbols());
333 }
334 EXPECT_GT(symbolsElfLoader->GetSymbols().size(), symbolsElfStrippedLoader->GetSymbols().size());
335
336 ASSERT_EQ(symbolsElfStrippedLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
337 EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(TEST_FILE_ELF), true);
338 if (HasFailure()) {
339 PrintSymbols(symbolsElfStrippedLoader->GetSymbols());
340 }
341
342 // no symbols not means failed.
343 EXPECT_EQ(TestLoadSymbols(SYMBOL_ELF_FILE, TEST_FILE_ELF_STRIPPED), true);
344
345 // no build id not means failed.
346 EXPECT_EQ(TestLoadSymbols(SYMBOL_ELF_FILE, TEST_FILE_ELF_STRIPPED_NOBUILDID), true);
347
348 EXPECT_EQ(TestLoadSymbols(SYMBOL_ELF_FILE, TEST_FILE_ELF_STRIPPED_BROKEN), false);
349 }
350
351 /**
352 * @tc.name: GetSymbolWithVaddr
353 * @tc.desc:
354 * @tc.type: FUNC
355 */
356 HWTEST_F(SymbolsFileTest, GetSymbolWithVaddr, TestSize.Level1)
357 {
358 if (access("/sys/kernel/notes", F_OK) != 0) {
359 printf("cannot access /sys/kernel/notes\n");
360 return;
361 }
362
363 auto symbols = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE);
364 if ((0 == getuid())) {
365 HLOGD("in root mode");
366 EXPECT_EQ(symbols->LoadSymbols(), true);
367 CheckSymbols(symbols);
368 } else {
369 EXPECT_EQ(symbols->LoadSymbols(), true);
370 if (!KptrRestrict()) {
371 HLOGD("NOT KptrRestrict");
372 if (!symbols->GetSymbols().empty()) {
373 CheckSymbols(symbols);
374 } else {
375 printf("we found this issue in linux-5.10\n");
376 }
377 } else {
378 HLOGD("KptrRestrict");
379 ASSERT_EQ(symbols->GetSymbols().empty(), true);
380 }
381 }
382 }
383
384 /**
385 * @tc.name: GetSymbolWithVaddr
386 * @tc.desc:
387 * @tc.type: FUNC
388 */
389 HWTEST_F(SymbolsFileTest, GetSymbolWithVaddr2, TestSize.Level1)
390 {
391 auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
392 ASSERT_EQ(elfSymbols->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
393 EXPECT_EQ(elfSymbols->LoadSymbols(TEST_FILE_ELF), true);
394 ASSERT_EQ(elfSymbols->GetSymbols().empty(), false);
395
396 /*
397 part of elf32_test's symbols
398 vaddr(hex) size(dec) name
399 00001000 0 _init
400 00001030 0
401 00001320 58 _start
402 00001512 27 main
403 0000145d 124 TestGlobalChildFunction
404 000014d9 57 TestGlobalParentFunction
405 // last one
406 00001b38 0 _fini
407
408 part of elf_test's symbols
409 vaddr(hex) size(dec) name
410 0000000000002000 0 _init
411 0000000000002020 0
412 00000000000022f0 47 _start
413 0000000000002478 15 main
414 00000000000023d9 110 TestGlobalChildFunction
415 0000000000002447 49 TestGlobalParentFunction
416 //last one
417 0000000000002aa8 0 _fini
418 */
419 #ifdef __arm__
420 ScopeDebugLevel tempLogLevel(LEVEL_MUCH, true);
421 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001000).Name(), "_init");
422 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001029).Name(), "_init");
423 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001320).Name(), "_start");
424 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001359).Name(), "_start");
425 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001512).Name(), "main");
426 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x0000152c).Name(), "main");
427 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x0000145d).Name(), "TestGlobalChildFunction");
428 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x000014d9).Name(), "TestGlobalParentFunction");
429 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001b38).Name(), "_fini");
430 #else
431 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002000).Name(), "_init");
432 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002019).Name(), "_init");
433 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x000022f0).Name(), "_start");
434 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x0000231e).Name(), "_start");
435 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002478).Name(), "main");
436 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002486).Name(), "main");
437 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x000023d9).Name(), "TestGlobalChildFunction");
438 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002447).Name(), "TestGlobalParentFunction");
439 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002aa8).Name(), "_fini");
440 #endif
441 if (HasFailure()) {
442 PrintSymbols(elfSymbols->GetSymbols());
443 }
444 }
445
446 /**
447 * @tc.name: GetSymbolWithVaddr
448 * @tc.desc:
449 * @tc.type: FUNC
450 */
451 HWTEST_F(SymbolsFileTest, GetSymbolWithVaddrFullMatch, TestSize.Level1)
452 {
453 auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
454 ASSERT_EQ(elfSymbols->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
455 if (elfSymbols->LoadSymbols(TEST_SYMBOLS_FILE_ELF)) {
456 ASSERT_EQ(elfSymbols->GetSymbols().empty(), false);
457 /*
458 nm -C --defined-only symbols_file_test_elf64
459 addr = 1000 mangle name = _init
460 addr = 1040 mangle name = _start
461 addr = 1070 mangle name = deregister_tm_clones
462 addr = 10a0 mangle name = register_tm_clones
463 addr = 10e0 mangle name = __do_global_dtors_aux
464 addr = 1120 mangle name = frame_dummy
465 addr = 1129 mangle name = main
466 addr = 1140 mangle name = __libc_csu_init
467 addr = 11b0 mangle name = __libc_csu_fini
468
469 //last one
470 addr = 11b8 mangle name = _fini
471
472 nm -C --defined-only symbols_file_test_elf32
473 00001000 t _init
474 00001070 T _start
475 000010c0 t deregister_tm_clones
476 00001100 t register_tm_clones
477 00001150 t __do_global_dtors_aux
478 000011a0 t frame_dummy
479 000011ad T main
480 000011d0 T __libc_csu_init
481 00001240 T __libc_csu_fini
482
483 // last one
484 0000124c T _fini
485 */
486 #ifdef __arm__
487 enum SymbolAddr : uint64_t {
488 INIT = 0X1000U,
489 START = 0X1070U,
490 DEREG = 0X10C0U,
491 REG = 0X1100U,
492 AUX = 0X1150U,
493 FRAME = 0X11A0U,
494 MAIN = 0X11ADU,
495 CSU_INIT = 0X11D0U,
496 CSU_FINI = 0X1240U,
497 FINI = 0X124CU,
498 };
499 #else
500 enum SymbolAddr : uint64_t {
501 INIT = 0X1000U,
502 START = 0X1040U,
503 DEREG = 0X1070U,
504 REG = 0X10A0U,
505 AUX = 0X10E0U,
506 FRAME = 0X1120U,
507 MAIN = 0X1129U,
508 CSU_INIT = 0X1140U,
509 CSU_FINI = 0X11B0U,
510 FINI = 0X11B8U,
511 };
512 #endif
513 for (uint64_t addr = SymbolAddr::INIT; addr < SymbolAddr::START; ++addr) {
514 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
515 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "_init");
516 }
517 }
518 for (uint64_t addr = SymbolAddr::START; addr < SymbolAddr::DEREG; ++addr) {
519 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
520 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "_start");
521 }
522 }
523 for (uint64_t addr = SymbolAddr::DEREG; addr < SymbolAddr::REG; ++addr) {
524 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
525 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "deregister_tm_clones");
526 }
527 }
528 for (uint64_t addr = SymbolAddr::REG; addr < SymbolAddr::AUX; ++addr) {
529 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
530 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "register_tm_clones");
531 }
532 }
533 for (uint64_t addr = SymbolAddr::AUX; addr < SymbolAddr::FRAME; ++addr) {
534 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
535 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "__do_global_dtors_aux");
536 }
537 }
538 for (uint64_t addr = SymbolAddr::FRAME; addr < SymbolAddr::MAIN; ++addr) {
539 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
540 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "frame_dummy");
541 }
542 }
543 for (uint64_t addr = SymbolAddr::MAIN; addr < SymbolAddr::CSU_INIT; ++addr) {
544 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
545 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "main");
546 }
547 }
548 for (uint64_t addr = SymbolAddr::CSU_INIT; addr < SymbolAddr::CSU_FINI; ++addr) {
549 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
550 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "__libc_csu_init");
551 }
552 }
553 for (uint64_t addr = SymbolAddr::CSU_FINI; addr < SymbolAddr::FINI; ++addr) {
554 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
555 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "__libc_csu_fini");
556 }
557 }
558 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(SymbolAddr::FINI).demangle_, "_fini");
559 if (HasFailure()) {
560 PrintSymbols(elfSymbols->GetSymbols());
561 }
562 }
563 }
564
565 /**
566 * @tc.name: GetVaddrInSymbols
567 * @tc.desc:
568 * @tc.type: FUNC
569 */
570 HWTEST_F(SymbolsFileTest, GetVaddrInSymbols, TestSize.Level1)
571 {
572 /*
573 00200000-002c5000 r--p 00000000 08:02 46400311
574 002c5000-00490000 r-xp 000c5000 08:02 4640031
575
576 [14] .text PROGBITS 00000000002c5000 000c5000
577
578 if ip is 0x46e6ab
579 1. find the map range is 002c5000-00490000
580 2. ip - map start(002c5000) = map section offset
581 3. map section offset + map page offset(000c5000) = elf file offset
582 4. elf file offset - exec file offset(000c5000)
583 = ip offset (ip always in exec file offset)
584 5. ip offset + exec begin vaddr(2c5000) = virtual ip in elf
585 */
586 auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
587 elfSymbols->textExecVaddrFileOffset_ = 0x000c5000;
588 elfSymbols->textExecVaddr_ = 0x002c5000;
589
590 // most easy case
591 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x002c5123, 0x002c5000, 0x000c5000), 0x002c5123U);
592
593 // ip and map both change
594 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0xFF2c5123, 0xFF2c5000, 0x000c5000), 0x002c5123U);
595 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x00000123, 0x00000000, 0x000c5000), 0x002c5123U);
596
597 // map page and offset change
598 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x002ca123, 0x002c5000, 0x000c0000), 0x002c5123U);
599 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x002c4123, 0x002c5000, 0x000c6000), 0x002c5123U);
600
601 // kernel dont care offset
602 auto kernelSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE);
603 EXPECT_EQ(kernelSymbols->GetVaddrInSymbols(0x001234, 0x002c5000, 0x000c5000), 0x001234U);
604 }
605
606 /**
607 * @tc.name: FindSymbolFile
608 * @tc.desc:
609 * @tc.type: FUNC
610 */
611 HWTEST_F(SymbolsFileTest, FindSymbolFile, TestSize.Level1)
612 {
613 auto symbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
614
615 std::vector<std::string> symbolsFileSearchPaths;
616 std::string symboleFilePath;
617
618 symboleFilePath = TEST_FILE_VMLINUX;
619 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), true);
620
621 symbolsFileSearchPaths.emplace_back(PATH_RESOURCE_TEST_DATA);
622 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
623
624 symbolsFileSearchPaths.clear();
625 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), true);
626
627 symboleFilePath = PATH_RESOURCE_TEST_DATA + TEST_FILE_VMLINUX;
628 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
629
630 symbolsFileSearchPaths.emplace_back(PATH_RESOURCE_TEST_DATA);
631 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
632
633 symboleFilePath = TEST_FILE_ELF;
634 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
635
636 symbolsFileSearchPaths.clear();
637 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), true);
638 }
639
640 /**
641 * @tc.name: GetBuildId
642 * @tc.desc:
643 * @tc.type: FUNC
644 */
645 HWTEST_F(SymbolsFileTest, GetBuildId, TestSize.Level1)
646 {
647 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
648 // empty elf
649 EXPECT_EQ(symbolsFile->GetBuildId().empty(), true);
650 // set search path
651 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
652
653 symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
654 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
655 // kernel elf
656 EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_VMLINUX), true);
657 EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
658
659 symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
660 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
661 // stripped elf
662 EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_ELF), true);
663 EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
664
665 symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
666 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
667 // stripped elf
668 EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_ELF_STRIPPED), true);
669 EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
670 }
671
672 /**
673 * @tc.name: ReadRoMemory
674 * @tc.desc:
675 * @tc.type: FUNC
676 */
677 HWTEST_F(SymbolsFileTest, ReadRoMemory, TestSize.Level1)
678 {
679 std::unique_ptr<SymbolsFile> defaultSymbolsFile = SymbolsFile::CreateSymbolsFile();
680
681 std::unique_ptr<SymbolsFile> symbolsFile =
682 SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_FILE_ELF_FULL_PATH);
683 std::string resolvedPath = CanonicalizeSpecPath(TEST_FILE_ELF_FULL_PATH.c_str());
684 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(resolvedPath.c_str(), "rb"),
685 fclose);
686
687 ASSERT_NE(symbolsFile, nullptr);
688 ASSERT_NE(fp, nullptr);
689
690 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
691
692 uint8_t freadByte = '\0';
693 uint8_t readRoByte = '\0';
694 uint64_t addr = 0x0;
695
696 // virtual function
697 EXPECT_EQ(defaultSymbolsFile->ReadRoMemory(addr, &readRoByte, 1), 0U);
698
699 // first byte
700 ASSERT_EQ(fread(&freadByte, 1, 1, fp.get()), 1U);
701 ASSERT_EQ(symbolsFile->ReadRoMemory(addr++, &readRoByte, 1), 1U);
702 ASSERT_EQ(freadByte, readRoByte);
703
704 while (fread(&freadByte, 1, 1, fp.get()) == 1U) {
705 EXPECT_EQ(symbolsFile->ReadRoMemory(addr++, &readRoByte, 1), 1U);
706 EXPECT_EQ(freadByte, readRoByte);
707 }
708
709 // EOF , out of file size should return 0
710 ASSERT_EQ(symbolsFile->ReadRoMemory(addr++, &readRoByte, 1), 0U);
711 }
712
713 struct sectionInfo {
714 const std::string name;
715 uint64_t addr;
716 uint64_t size;
717 uint64_t offset;
718 };
719
720 /**
721 * @tc.name: GetSectionInfo
722 * @tc.desc:
723 * @tc.type: FUNC
724 */
725 HWTEST_F(SymbolsFileTest, GetSectionInfo, TestSize.Level1)
726 {
727 std::unique_ptr<SymbolsFile> symbolsFile =
728 SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_FILE_ELF_FULL_PATH);
729 ASSERT_EQ(symbolsFile->LoadDebugInfo(), true);
730 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
731
732 /*
733 from readelf -e elf32_test
734 32bit
735 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
736 [ 0] NULL 00000000 000000 000000 00 0 0 0
737 [ 1] .interp PROGBITS 000001b4 0001b4 000013 00 A 0 0 1
738 [ 2] .note.gnu.build-i NOTE 000001c8 0001c8 000024 00 A 0 0 4
739 [16] .text PROGBITS 00001320 001320 000818 00 AX 0 0 16
740 [19] .eh_frame_hdr PROGBITS 00002034 002034 0000dc 00 A 0 0 4
741 [20] .eh_frame PROGBITS 00002110 002110 0003a0 00 A 0 0 4
742 [29] .symtab SYMTAB 00000000 003034 000710 10 30 50 4
743 [30] .strtab STRTAB 00000000 003744 000c3d 00 0 0 1
744 [31] .shstrtab STRTAB 00000000 004381 00012a 00 0 0 1
745
746 from readelf -e elf_test
747 64bit
748 Section Headers:
749 [Nr] Name Type Address Offset
750 Size EntSize Flags Link Info Align
751 [ 0] NULL 0000000000000000 00000000
752 0000000000000000 0000000000000000 0 0 0
753 [ 1] .interp PROGBITS 0000000000000318 00000318
754 000000000000001c 0000000000000000 A 0 0 1
755 [ 2] .note.gnu.propert NOTE 0000000000000338 00000338
756 0000000000000020 0000000000000000 A 0 0 8
757 [16] .text PROGBITS 00000000000022f0 000022f0
758 00000000000007b5 0000000000000000 AX 0 0 16
759 [19] .eh_frame_hdr PROGBITS 0000000000003034 00003034
760 00000000000000bc 0000000000000000 A 0 0 4
761 [20] .eh_frame PROGBITS 00000000000030f0 000030f0
762 0000000000000320 0000000000000000 A 0 0 8
763 [29] .symtab SYMTAB 0000000000000000 00004040
764 00000000000009f0 0000000000000018 30 50 8
765 [30] .strtab STRTAB 0000000000000000 00004a30
766 0000000000000bbb 0000000000000000 0 0 1
767 [31] .shstrtab STRTAB 0000000000000000 000055eb
768 000000000000012c 0000000000000000 0 0 1
769 */
770 #ifdef __arm__
771 const std::vector<sectionInfo> sectionCheckList = {
772 {".note.gnu.build-id", 0x000001c8, 0x000024, 0x0001c8},
773 {".text", 0x00001320, 0x000818, 0x001320},
774 {".eh_frame_hdr", 0x00002034, 0x0000dc, 0x002034},
775 {".eh_frame", 0x00002110, 0x0003a0, 0x002110},
776 {".symtab", 0x00000000, 0x000710, 0x003034},
777 {".strtab", 0x00000000, 0x000c3d, 0x003744},
778 {".shstrtab", 0x00000000, 0x00012a, 0x004381},
779 };
780 #else
781 const std::vector<sectionInfo> sectionCheckList = {
782 {".note.gnu.build-id", 0x0000000000000358, 0x0000000000000024, 0x00000358},
783 {".text", 0x00000000000022f0, 0x00000000000007b5, 0x000022f0},
784 {".eh_frame_hdr", 0x0000000000003034, 0x00000000000000bc, 0x00003034},
785 {".eh_frame", 0x00000000000030f0, 0x0000000000000320, 0x000030f0},
786 {".symtab", 0x00000000, 0x00000000000009f0, 0x00004040},
787 {".strtab", 0x00000000, 0x0000000000000bbb, 0x00004a30},
788 {".shstrtab", 0x00000000, 0x000000000000012c, 0x000055eb},
789 };
790 #endif
791 for (sectionInfo info : sectionCheckList) {
792 uint64_t addr;
793 uint64_t size;
794 uint64_t offset;
795 EXPECT_EQ(symbolsFile->GetSectionInfo(info.name, addr, size, offset), true);
796 EXPECT_EQ(addr, info.addr);
797 EXPECT_EQ(size, info.size);
798 EXPECT_EQ(offset, info.offset);
799 if (HasFailure()) {
800 printf("sectionInfo check failed at '%s', %" PRIx64 ",%" PRIx64 ",%" PRIx64 "\n",
801 info.name.c_str(), info.addr, info.size, info.offset);
802 }
803 }
804 }
805
806 #ifndef __arm__
807 /**
808 * @tc.name: GetHDRSectionInfo
809 * @tc.desc:
810 * @tc.type: FUNC
811 */
812 HWTEST_F(SymbolsFileTest, GetHDRSectionInfo, TestSize.Level1)
813 {
814 std::unique_ptr<SymbolsFile> symbolsFile =
815 SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_FILE_ELF_FULL_PATH);
816 const constexpr unsigned int fdeTableItemSize = 8;
817
818 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
819 ASSERT_EQ(symbolsFile->LoadDebugInfo(), true);
820
821 uint64_t ehFrameHdrElfOffset;
822 uint64_t fdeTableElfOffset;
823 uint64_t fdeTableSize;
824
825 /*
826 readelf -e elf32_test | grep .eh_frame_hdr
827 [19] .eh_frame_hdr PROGBITS 00002034 002034 0000dc 00 A 0 0 4
828
829 readelf --debug-dump=frames elf32_test | grep FDE | wc -l
830 26
831
832 readelf -e elf_test | grep .eh_frame_hdr
833 [19] .eh_frame_hdr PROGBITS 0000000000003034 00003034
834
835 readelf --debug-dump=frames elf_test | grep FDE | wc -l
836 22
837 */
838 symbolsFile->GetHDRSectionInfo(ehFrameHdrElfOffset, fdeTableElfOffset, fdeTableSize);
839
840 EXPECT_EQ(ehFrameHdrElfOffset, 0x00003034u);
841 EXPECT_EQ(fdeTableSize, 22U * fdeTableItemSize);
842 }
843
844 /**
845 * @tc.name: GetHDRSectionInfo
846 * @tc.desc:
847 * @tc.type: FUNC
848 */
849 HWTEST_F(SymbolsFileTest, GetHDRSectionInfoStripped, TestSize.Level1)
850 {
851 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(
852 SYMBOL_ELF_FILE, PATH_RESOURCE_TEST_DATA + TEST_FILE_ELF_STRIPPED_NOEFHDR);
853
854 ASSERT_EQ(symbolsFile->LoadDebugInfo(), true);
855
856 uint64_t ehFrameHdrElfOffset;
857 uint64_t fdeTableElfOffset;
858 uint64_t fdeTableSize;
859
860 symbolsFile->GetHDRSectionInfo(ehFrameHdrElfOffset, fdeTableElfOffset, fdeTableSize);
861 uint64_t addr = 0;
862 uint64_t size = 0;
863 uint64_t offset = 0;
864 EXPECT_EQ(symbolsFile->GetSectionInfo(EH_FRAME_HR, addr, size, offset), false);
865 EXPECT_EQ(offset, 0U);
866 EXPECT_EQ(size, 0U);
867 EXPECT_EQ(addr, 0U);
868 }
869 #endif
870
871 /**
872 * @tc.name: CreateSymbolsFile
873 * @tc.desc:
874 * @tc.type: FUNC
875 */
876 HWTEST_F(SymbolsFileTest, CreateSymbolsFile, TestSize.Level1)
877 {
878 EXPECT_NE(SymbolsFile::CreateSymbolsFile(), nullptr);
879 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE), nullptr);
880 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE), nullptr);
881 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE), nullptr);
882 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_JAVA_FILE), nullptr);
883 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_JS_FILE), nullptr);
884 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE), nullptr);
885 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SymbolsFileType(-1)), nullptr);
886 EXPECT_EQ(SymbolsFile::CreateSymbolsFile(SymbolsFileType(-2))->symbolFileType_,
887 SYMBOL_UNKNOW_FILE);
888
889 EXPECT_EQ(SymbolsFile::CreateSymbolsFile(KERNEL_MMAP_NAME)->symbolFileType_,
890 SYMBOL_KERNEL_FILE);
891 EXPECT_EQ(SymbolsFile::CreateSymbolsFile(TEST_FILE_ELF_FULL_PATH)->symbolFileType_,
892 SYMBOL_ELF_FILE);
893 }
894
895 /**
896 * @tc.name: LoadSymbolsFromSaved
897 * @tc.desc:
898 * @tc.type: FUNC
899 */
900 HWTEST_F(SymbolsFileTest, LoadSymbolsFromSaved, TestSize.Level1)
901 {
902 SymbolFileStruct sfs;
903 for (unsigned int type = 0; type < SYMBOL_UNKNOW_FILE; type++) {
904 sfs.filePath_ = std::to_string(rnd_());
905 sfs.symbolType_ = type;
906 sfs.textExecVaddrFileOffset_ = rnd_();
907 sfs.textExecVaddr_ = rnd_();
908 sfs.buildId_ = std::to_string(rnd_());
909 int nameIndex = 0;
910 // after LoadSymbolsFromSaved it will sort from low to high
911 // so we make a order item to test
912 constexpr int rndMax = 10000;
913 std::uniform_int_distribution<int> rndLimi(0, rndMax);
914 sfs.symbolStructs_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
915 std::to_string(nameIndex));
916 nameIndex++;
917 sfs.symbolStructs_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
918 std::to_string(nameIndex));
919 nameIndex++;
920 sfs.symbolStructs_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
921 std::to_string(nameIndex));
922 nameIndex++;
923
924 // setup the min vaddr
925
926 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::LoadSymbolsFromSaved(sfs);
927
928 EXPECT_EQ(symbolsFile->filePath_, sfs.filePath_);
929 EXPECT_EQ(symbolsFile->symbolFileType_, sfs.symbolType_);
930 EXPECT_EQ(symbolsFile->textExecVaddr_, sfs.textExecVaddr_);
931 EXPECT_EQ(symbolsFile->textExecVaddrFileOffset_, sfs.textExecVaddrFileOffset_);
932 EXPECT_EQ(symbolsFile->GetBuildId(), sfs.buildId_);
933 EXPECT_EQ(symbolsFile->GetSymbols().size(), sfs.symbolStructs_.size());
934
935 for (Symbol symbol : symbolsFile->GetSymbols()) {
936 SymbolStruct symbolStruct = sfs.symbolStructs_.front();
937 EXPECT_EQ(symbol.funcVaddr_, symbolStruct.vaddr_);
938 EXPECT_EQ(symbol.len_, symbolStruct.len_);
939 EXPECT_EQ(symbol.name_, symbolStruct.symbolName_);
940 sfs.symbolStructs_.erase(sfs.symbolStructs_.begin());
941 }
942 }
943 }
944
945 /**
946 * @tc.name: exportSymbolToFileFormatMatched
947 * @tc.desc:
948 * @tc.type: FUNC
949 */
950 HWTEST_F(SymbolsFileTest, exportSymbolToFileFormatMatched, TestSize.Level1)
951 {
952 for (int type = 0; type < SYMBOL_UNKNOW_FILE; type++) {
953 auto symbolsFile = SymbolsFile::CreateSymbolsFile();
954 symbolsFile->filePath_ = std::to_string(rnd_());
955 symbolsFile->symbolFileType_ = static_cast<SymbolsFileType>(type);
956 symbolsFile->textExecVaddrFileOffset_ = rnd_();
957 symbolsFile->buildId_ = std::to_string(rnd_());
958 int nameIndex = 0;
959 // after LoadSymbolsFromSaved it will sort from low to high
960 // so we make a order item to test
961 constexpr int rndMax = 10000;
962 std::uniform_int_distribution<int> rndLimi(0, rndMax);
963 symbolsFile->symbols_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
964 std::to_string(nameIndex), symbolsFile->filePath_);
965 nameIndex++;
966 symbolsFile->symbols_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
967 std::to_string(nameIndex), symbolsFile->filePath_);
968 nameIndex++;
969 symbolsFile->symbols_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
970 std::to_string(nameIndex), symbolsFile->filePath_);
971 nameIndex++;
972
973 // setup the min vaddr
974 symbolsFile->textExecVaddr_ = std::numeric_limits<uint64_t>::max();
975
976 for (auto &symbol : symbolsFile->symbols_) {
977 symbolsFile->textExecVaddr_ = std::min(symbol.funcVaddr_, symbolsFile->textExecVaddr_);
978 }
979
980 // access last one to make it as matched.
981 uint64_t matchedVaddr = symbolsFile->symbols_.back().funcVaddr_;
982 auto symbol = symbolsFile->GetSymbolWithVaddr(matchedVaddr);
983 EXPECT_EQ(symbol.funcVaddr_, matchedVaddr);
984 if (HasFailure()) {
985 PrintSymbols(symbolsFile->GetSymbols());
986 }
987
988 SymbolFileStruct sfs {};
989 symbolsFile->ExportSymbolToFileFormat(sfs);
990
991 EXPECT_EQ(symbolsFile->symbolFileType_, sfs.symbolType_);
992 EXPECT_EQ(symbolsFile->textExecVaddrFileOffset_, sfs.textExecVaddrFileOffset_);
993 EXPECT_EQ(symbolsFile->GetBuildId(), sfs.buildId_);
994
995 // matched one should be remove
996 EXPECT_EQ(sfs.symbolStructs_.size(), 1u);
997 for (SymbolStruct symbolStruct : sfs.symbolStructs_) {
998 // nomore found for matched vaddr
999 EXPECT_EQ(symbolStruct.vaddr_, matchedVaddr);
1000 }
1001 }
1002 }
1003
1004 /**
1005 * @tc.name: UpdateBuildIdIfMatch
1006 * @tc.desc:
1007 * @tc.type: FUNC
1008 */
1009 HWTEST_F(SymbolsFileTest, UpdateBuildIdIfMatch, TestSize.Level1)
1010 {
1011 auto file = SymbolsFile::CreateSymbolsFile();
1012 file->buildId_ = "123";
1013 file->UpdateBuildIdIfMatch("456");
1014 EXPECT_STREQ(file->buildId_.c_str(), "123");
1015 EXPECT_STRNE(file->buildId_.c_str(), "456");
1016 }
1017 } // namespace HiPerf
1018 } // namespace Developtools
1019 } // namespace OHOS
1020