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 // read from kernel runtime
271 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE);
272 ScopeDebugLevel tempLogLevel(LEVEL_VERBOSE);
273 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
274
275 const std::vector<Symbol> &symbols = symbolsFile->GetSymbols();
276
277 if (KptrRestrict()) {
278 EXPECT_EQ(symbols.empty(), true);
279 } else {
280 EXPECT_EQ(symbols.empty(), false);
281 }
282
283 std::string modulesMap = ReadFileToString("/proc/modules");
284 int lines = std::count(modulesMap.begin(), modulesMap.end(), '\n');
285 if (lines < 0) {
286 return;
287 }
288 std::set<std::string> modulesCount;
289 for (auto &symbol : symbols) {
290 if (symbol.module_.length()) {
291 modulesCount.emplace(symbol.module_);
292 }
293 }
294
295 // add [kernel.kallsyms]
296 EXPECT_GE(modulesCount.size(), lines + 1u);
297 if (HasFailure()) {
298 for (auto &module : modulesCount) {
299 printf("%s\n", module.c_str());
300 }
301 }
302
303 // try vmlinux
304 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX), true);
305 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX_STRIPPED), true);
306 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX_STRIPPED_NOBUILDID), true);
307 // will be load from runtime, still return true
308 EXPECT_EQ(TestLoadSymbols(SYMBOL_KERNEL_FILE, TEST_FILE_VMLINUX_STRIPPED_BROKEN), true);
309 }
310
311 /**
312 * @tc.name: LoaderElfSymbols
313 * @tc.desc:
314 * @tc.type: FUNC
315 */
316 HWTEST_F(SymbolsFileTest, LoadElfSymbols, TestSize.Level1)
317 {
318 auto symbolsElfLoader = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
319 auto symbolsElfStrippedLoader = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
320 ScopeDebugLevel tempLogLevel(LEVEL_VERBOSE);
321
322 EXPECT_EQ(symbolsElfLoader->LoadSymbols(), false);
323
324 ASSERT_EQ(symbolsElfLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
325 EXPECT_EQ(symbolsElfLoader->LoadSymbols(TEST_FILE_ELF), true);
326 if (HasFailure()) {
327 PrintSymbols(symbolsElfLoader->GetSymbols());
328 }
329
330 ASSERT_EQ(symbolsElfStrippedLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
331 EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(TEST_FILE_ELF_STRIPPED), true);
332 if (HasFailure()) {
333 PrintSymbols(symbolsElfStrippedLoader->GetSymbols());
334 }
335 EXPECT_GT(symbolsElfLoader->GetSymbols().size(), symbolsElfStrippedLoader->GetSymbols().size());
336
337 ASSERT_EQ(symbolsElfStrippedLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
338 EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(TEST_FILE_ELF), true);
339 if (HasFailure()) {
340 PrintSymbols(symbolsElfStrippedLoader->GetSymbols());
341 }
342
343 // no symbols not means failed.
344 EXPECT_EQ(TestLoadSymbols(SYMBOL_ELF_FILE, TEST_FILE_ELF_STRIPPED), true);
345
346 // no build id not means failed.
347 EXPECT_EQ(TestLoadSymbols(SYMBOL_ELF_FILE, TEST_FILE_ELF_STRIPPED_NOBUILDID), true);
348
349 EXPECT_EQ(TestLoadSymbols(SYMBOL_ELF_FILE, TEST_FILE_ELF_STRIPPED_BROKEN), false);
350 }
351
352 /**
353 * @tc.name: GetSymbolWithVaddr
354 * @tc.desc:
355 * @tc.type: FUNC
356 */
357 HWTEST_F(SymbolsFileTest, GetSymbolWithVaddr, TestSize.Level1)
358 {
359 auto symbols = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE);
360
361 if ((0 == getuid())) {
362 HLOGD("in root mode");
363 EXPECT_EQ(symbols->LoadSymbols(), true);
364 CheckSymbols(symbols);
365 } else {
366 EXPECT_EQ(symbols->LoadSymbols(), true);
367 if (!KptrRestrict()) {
368 HLOGD("NOT KptrRestrict");
369 if (!symbols->GetSymbols().empty()) {
370 CheckSymbols(symbols);
371 } else {
372 printf("we found this issue in linux-5.10\n");
373 }
374 } else {
375 HLOGD("KptrRestrict");
376 ASSERT_EQ(symbols->GetSymbols().empty(), true);
377 }
378 }
379 }
380
381 /**
382 * @tc.name: GetSymbolWithVaddr
383 * @tc.desc:
384 * @tc.type: FUNC
385 */
386 HWTEST_F(SymbolsFileTest, GetSymbolWithVaddr2, TestSize.Level1)
387 {
388 auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
389 ASSERT_EQ(elfSymbols->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
390 EXPECT_EQ(elfSymbols->LoadSymbols(TEST_FILE_ELF), true);
391 ASSERT_EQ(elfSymbols->GetSymbols().empty(), false);
392
393 /*
394 part of elf32_test's symbols
395 vaddr(hex) size(dec) name
396 00001000 0 _init
397 00001030 0
398 00001320 58 _start
399 00001512 27 main
400 0000145d 124 TestGlobalChildFunction
401 000014d9 57 TestGlobalParentFunction
402 // last one
403 00001b38 0 _fini
404
405 part of elf_test's symbols
406 vaddr(hex) size(dec) name
407 0000000000002000 0 _init
408 0000000000002020 0
409 00000000000022f0 47 _start
410 0000000000002478 15 main
411 00000000000023d9 110 TestGlobalChildFunction
412 0000000000002447 49 TestGlobalParentFunction
413 //last one
414 0000000000002aa8 0 _fini
415 */
416 #ifdef __arm__
417 ScopeDebugLevel tempLogLevel(LEVEL_MUCH, true);
418 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001000).Name(), "_init");
419 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001029).Name(), "_init");
420 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001320).Name(), "_start");
421 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001359).Name(), "_start");
422 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001512).Name(), "main");
423 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x0000152c).Name(), "main");
424 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x0000145d).Name(), "TestGlobalChildFunction");
425 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x000014d9).Name(), "TestGlobalParentFunction");
426 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00001b38).Name(), "_fini");
427 #else
428 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002000).Name(), "_init");
429 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002019).Name(), "_init");
430 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x000022f0).Name(), "_start");
431 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x0000231e).Name(), "_start");
432 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002478).Name(), "main");
433 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002486).Name(), "main");
434 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x000023d9).Name(), "TestGlobalChildFunction");
435 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002447).Name(), "TestGlobalParentFunction");
436 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(0x00002aa8).Name(), "_fini");
437 #endif
438 if (HasFailure()) {
439 PrintSymbols(elfSymbols->GetSymbols());
440 }
441 }
442
443 /**
444 * @tc.name: GetSymbolWithVaddr
445 * @tc.desc:
446 * @tc.type: FUNC
447 */
448 HWTEST_F(SymbolsFileTest, GetSymbolWithVaddrFullMatch, TestSize.Level1)
449 {
450 auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
451 ASSERT_EQ(elfSymbols->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
452 if (elfSymbols->LoadSymbols(TEST_SYMBOLS_FILE_ELF)) {
453 ASSERT_EQ(elfSymbols->GetSymbols().empty(), false);
454 /*
455 nm -C --defined-only symbols_file_test_elf64
456 addr = 1000 mangle name = _init
457 addr = 1040 mangle name = _start
458 addr = 1070 mangle name = deregister_tm_clones
459 addr = 10a0 mangle name = register_tm_clones
460 addr = 10e0 mangle name = __do_global_dtors_aux
461 addr = 1120 mangle name = frame_dummy
462 addr = 1129 mangle name = main
463 addr = 1140 mangle name = __libc_csu_init
464 addr = 11b0 mangle name = __libc_csu_fini
465
466 //last one
467 addr = 11b8 mangle name = _fini
468
469 nm -C --defined-only symbols_file_test_elf32
470 00001000 t _init
471 00001070 T _start
472 000010c0 t deregister_tm_clones
473 00001100 t register_tm_clones
474 00001150 t __do_global_dtors_aux
475 000011a0 t frame_dummy
476 000011ad T main
477 000011d0 T __libc_csu_init
478 00001240 T __libc_csu_fini
479
480 // last one
481 0000124c T _fini
482 */
483 #ifdef __arm__
484 enum SymbolAddr : uint64_t {
485 INIT = 0X1000U,
486 START = 0X1070U,
487 DEREG = 0X10C0U,
488 REG = 0X1100U,
489 AUX = 0X1150U,
490 FRAME = 0X11A0U,
491 MAIN = 0X11ADU,
492 CSU_INIT = 0X11D0U,
493 CSU_FINI = 0X1240U,
494 FINI = 0X124CU,
495 };
496 #else
497 enum SymbolAddr : uint64_t {
498 INIT = 0X1000U,
499 START = 0X1040U,
500 DEREG = 0X1070U,
501 REG = 0X10A0U,
502 AUX = 0X10E0U,
503 FRAME = 0X1120U,
504 MAIN = 0X1129U,
505 CSU_INIT = 0X1140U,
506 CSU_FINI = 0X11B0U,
507 FINI = 0X11B8U,
508 };
509 #endif
510 for (uint64_t addr = SymbolAddr::INIT; addr < SymbolAddr::START; ++addr) {
511 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
512 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "_init");
513 }
514 }
515 for (uint64_t addr = SymbolAddr::START; addr < SymbolAddr::DEREG; ++addr) {
516 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
517 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "_start");
518 }
519 }
520 for (uint64_t addr = SymbolAddr::DEREG; addr < SymbolAddr::REG; ++addr) {
521 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
522 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "deregister_tm_clones");
523 }
524 }
525 for (uint64_t addr = SymbolAddr::REG; addr < SymbolAddr::AUX; ++addr) {
526 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
527 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "register_tm_clones");
528 }
529 }
530 for (uint64_t addr = SymbolAddr::AUX; addr < SymbolAddr::FRAME; ++addr) {
531 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
532 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "__do_global_dtors_aux");
533 }
534 }
535 for (uint64_t addr = SymbolAddr::FRAME; addr < SymbolAddr::MAIN; ++addr) {
536 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
537 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "frame_dummy");
538 }
539 }
540 for (uint64_t addr = SymbolAddr::MAIN; addr < SymbolAddr::CSU_INIT; ++addr) {
541 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
542 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "main");
543 }
544 }
545 for (uint64_t addr = SymbolAddr::CSU_INIT; addr < SymbolAddr::CSU_FINI; ++addr) {
546 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
547 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "__libc_csu_init");
548 }
549 }
550 for (uint64_t addr = SymbolAddr::CSU_FINI; addr < SymbolAddr::FINI; ++addr) {
551 if (elfSymbols->GetSymbolWithVaddr(addr).isValid()) {
552 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(addr).demangle_, "__libc_csu_fini");
553 }
554 }
555 EXPECT_EQ(elfSymbols->GetSymbolWithVaddr(SymbolAddr::FINI).demangle_, "_fini");
556 if (HasFailure()) {
557 PrintSymbols(elfSymbols->GetSymbols());
558 }
559 }
560 }
561
562 /**
563 * @tc.name: GetVaddrInSymbols
564 * @tc.desc:
565 * @tc.type: FUNC
566 */
567 HWTEST_F(SymbolsFileTest, GetVaddrInSymbols, TestSize.Level1)
568 {
569 /*
570 00200000-002c5000 r--p 00000000 08:02 46400311
571 002c5000-00490000 r-xp 000c5000 08:02 4640031
572
573 [14] .text PROGBITS 00000000002c5000 000c5000
574
575 if ip is 0x46e6ab
576 1. find the map range is 002c5000-00490000
577 2. ip - map start(002c5000) = map section offset
578 3. map section offset + map page offset(000c5000) = elf file offset
579 4. elf file offset - exec file offset(000c5000)
580 = ip offset (ip always in exec file offset)
581 5. ip offset + exec begin vaddr(2c5000) = virtual ip in elf
582 */
583 auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
584 elfSymbols->textExecVaddrFileOffset_ = 0x000c5000;
585 elfSymbols->textExecVaddr_ = 0x002c5000;
586
587 // most easy case
588 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x002c5123, 0x002c5000, 0x000c5000), 0x002c5123U);
589
590 // ip and map both change
591 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0xFF2c5123, 0xFF2c5000, 0x000c5000), 0x002c5123U);
592 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x00000123, 0x00000000, 0x000c5000), 0x002c5123U);
593
594 // map page and offset change
595 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x002ca123, 0x002c5000, 0x000c0000), 0x002c5123U);
596 EXPECT_EQ(elfSymbols->GetVaddrInSymbols(0x002c4123, 0x002c5000, 0x000c6000), 0x002c5123U);
597
598 // kernel dont care offset
599 auto kernelSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE);
600 EXPECT_EQ(kernelSymbols->GetVaddrInSymbols(0x001234, 0x002c5000, 0x000c5000), 0x001234U);
601 }
602
603 /**
604 * @tc.name: FindSymbolFile
605 * @tc.desc:
606 * @tc.type: FUNC
607 */
608 HWTEST_F(SymbolsFileTest, FindSymbolFile, TestSize.Level1)
609 {
610 auto symbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
611
612 std::vector<std::string> symbolsFileSearchPaths;
613 std::string symboleFilePath;
614
615 symboleFilePath = TEST_FILE_VMLINUX;
616 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), true);
617
618 symbolsFileSearchPaths.emplace_back(PATH_RESOURCE_TEST_DATA);
619 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
620
621 symbolsFileSearchPaths.clear();
622 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), true);
623
624 symboleFilePath = PATH_RESOURCE_TEST_DATA + TEST_FILE_VMLINUX;
625 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
626
627 symbolsFileSearchPaths.emplace_back(PATH_RESOURCE_TEST_DATA);
628 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
629
630 symboleFilePath = TEST_FILE_ELF;
631 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), false);
632
633 symbolsFileSearchPaths.clear();
634 EXPECT_EQ(symbols->FindSymbolFile(symbolsFileSearchPaths, symboleFilePath).empty(), true);
635 }
636
637 /**
638 * @tc.name: GetBuildId
639 * @tc.desc:
640 * @tc.type: FUNC
641 */
642 HWTEST_F(SymbolsFileTest, GetBuildId, TestSize.Level1)
643 {
644 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
645 // empty elf
646 EXPECT_EQ(symbolsFile->GetBuildId().empty(), true);
647 // set search path
648 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
649
650 symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
651 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
652 // kernel elf
653 EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_VMLINUX), true);
654 EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
655
656 symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
657 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
658 // stripped elf
659 EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_ELF), true);
660 EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
661
662 symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
663 ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
664 // stripped elf
665 EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_ELF_STRIPPED), true);
666 EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
667 }
668
669 /**
670 * @tc.name: ReadRoMemory
671 * @tc.desc:
672 * @tc.type: FUNC
673 */
674 HWTEST_F(SymbolsFileTest, ReadRoMemory, TestSize.Level1)
675 {
676 std::unique_ptr<SymbolsFile> defaultSymbolsFile = SymbolsFile::CreateSymbolsFile();
677
678 std::unique_ptr<SymbolsFile> symbolsFile =
679 SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_FILE_ELF_FULL_PATH);
680 std::string resolvedPath = CanonicalizeSpecPath(TEST_FILE_ELF_FULL_PATH.c_str());
681 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(resolvedPath.c_str(), "rb"),
682 fclose);
683
684 ASSERT_NE(symbolsFile, nullptr);
685 ASSERT_NE(fp, nullptr);
686
687 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
688
689 uint8_t freadByte = '\0';
690 uint8_t readRoByte = '\0';
691 uint64_t addr = 0x0;
692
693 // virtual function
694 EXPECT_EQ(defaultSymbolsFile->ReadRoMemory(addr, &readRoByte, 1), 0U);
695
696 // first byte
697 ASSERT_EQ(fread(&freadByte, 1, 1, fp.get()), 1U);
698 ASSERT_EQ(symbolsFile->ReadRoMemory(addr++, &readRoByte, 1), 1U);
699 ASSERT_EQ(freadByte, readRoByte);
700
701 while (fread(&freadByte, 1, 1, fp.get()) == 1U) {
702 EXPECT_EQ(symbolsFile->ReadRoMemory(addr++, &readRoByte, 1), 1U);
703 EXPECT_EQ(freadByte, readRoByte);
704 }
705
706 // EOF , out of file size should return 0
707 ASSERT_EQ(symbolsFile->ReadRoMemory(addr++, &readRoByte, 1), 0U);
708 }
709
710 struct sectionInfo {
711 const std::string name;
712 uint64_t addr;
713 uint64_t size;
714 uint64_t offset;
715 };
716
717 /**
718 * @tc.name: GetSectionInfo
719 * @tc.desc:
720 * @tc.type: FUNC
721 */
722 HWTEST_F(SymbolsFileTest, GetSectionInfo, TestSize.Level1)
723 {
724 std::unique_ptr<SymbolsFile> symbolsFile =
725 SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_FILE_ELF_FULL_PATH);
726 ASSERT_EQ(symbolsFile->LoadDebugInfo(), true);
727
728 /*
729 from readelf -e elf32_test
730 32bit
731 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
732 [ 0] NULL 00000000 000000 000000 00 0 0 0
733 [ 1] .interp PROGBITS 000001b4 0001b4 000013 00 A 0 0 1
734 [ 2] .note.gnu.build-i NOTE 000001c8 0001c8 000024 00 A 0 0 4
735 [16] .text PROGBITS 00001320 001320 000818 00 AX 0 0 16
736 [19] .eh_frame_hdr PROGBITS 00002034 002034 0000dc 00 A 0 0 4
737 [20] .eh_frame PROGBITS 00002110 002110 0003a0 00 A 0 0 4
738 [29] .symtab SYMTAB 00000000 003034 000710 10 30 50 4
739 [30] .strtab STRTAB 00000000 003744 000c3d 00 0 0 1
740 [31] .shstrtab STRTAB 00000000 004381 00012a 00 0 0 1
741
742 from readelf -e elf_test
743 64bit
744 Section Headers:
745 [Nr] Name Type Address Offset
746 Size EntSize Flags Link Info Align
747 [ 0] NULL 0000000000000000 00000000
748 0000000000000000 0000000000000000 0 0 0
749 [ 1] .interp PROGBITS 0000000000000318 00000318
750 000000000000001c 0000000000000000 A 0 0 1
751 [ 2] .note.gnu.propert NOTE 0000000000000338 00000338
752 0000000000000020 0000000000000000 A 0 0 8
753 [16] .text PROGBITS 00000000000022f0 000022f0
754 00000000000007b5 0000000000000000 AX 0 0 16
755 [19] .eh_frame_hdr PROGBITS 0000000000003034 00003034
756 00000000000000bc 0000000000000000 A 0 0 4
757 [20] .eh_frame PROGBITS 00000000000030f0 000030f0
758 0000000000000320 0000000000000000 A 0 0 8
759 [29] .symtab SYMTAB 0000000000000000 00004040
760 00000000000009f0 0000000000000018 30 50 8
761 [30] .strtab STRTAB 0000000000000000 00004a30
762 0000000000000bbb 0000000000000000 0 0 1
763 [31] .shstrtab STRTAB 0000000000000000 000055eb
764 000000000000012c 0000000000000000 0 0 1
765 */
766 #ifdef __arm__
767 const std::vector<sectionInfo> sectionCheckList = {
768 {".note.gnu.build-id", 0x000001c8, 0x000024, 0x0001c8},
769 {".text", 0x00001320, 0x000818, 0x001320},
770 {".eh_frame_hdr", 0x00002034, 0x0000dc, 0x002034},
771 {".eh_frame", 0x00002110, 0x0003a0, 0x002110},
772 {".symtab", 0x00000000, 0x000710, 0x003034},
773 {".strtab", 0x00000000, 0x000c3d, 0x003744},
774 {".shstrtab", 0x00000000, 0x00012a, 0x004381},
775 };
776 #else
777 const std::vector<sectionInfo> sectionCheckList = {
778 {".note.gnu.build-id", 0x0000000000000358, 0x0000000000000024, 0x00000358},
779 {".text", 0x00000000000022f0, 0x00000000000007b5, 0x000022f0},
780 {".eh_frame_hdr", 0x0000000000003034, 0x00000000000000bc, 0x00003034},
781 {".eh_frame", 0x00000000000030f0, 0x0000000000000320, 0x000030f0},
782 {".symtab", 0x00000000, 0x00000000000009f0, 0x00004040},
783 {".strtab", 0x00000000, 0x0000000000000bbb, 0x00004a30},
784 {".shstrtab", 0x00000000, 0x000000000000012c, 0x000055eb},
785 };
786 #endif
787 for (sectionInfo info : sectionCheckList) {
788 uint64_t addr;
789 uint64_t size;
790 uint64_t offset;
791 EXPECT_EQ(symbolsFile->GetSectionInfo(info.name, addr, size, offset), true);
792 EXPECT_EQ(addr, info.addr);
793 EXPECT_EQ(size, info.size);
794 EXPECT_EQ(offset, info.offset);
795 if (HasFailure()) {
796 printf("sectionInfo check failed at '%s', %" PRIx64 ",%" PRIx64 ",%" PRIx64 "\n",
797 info.name.c_str(), info.addr, info.size, info.offset);
798 }
799 }
800 }
801
802 #ifndef __arm__
803 /**
804 * @tc.name: GetHDRSectionInfo
805 * @tc.desc:
806 * @tc.type: FUNC
807 */
808 HWTEST_F(SymbolsFileTest, GetHDRSectionInfo, TestSize.Level1)
809 {
810 std::unique_ptr<SymbolsFile> symbolsFile =
811 SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_FILE_ELF_FULL_PATH);
812 const constexpr unsigned int fdeTableItemSize = 8;
813
814 ASSERT_EQ(symbolsFile->LoadSymbols(), true);
815
816 uint64_t ehFrameHdrElfOffset;
817 uint64_t fdeTableElfOffset;
818 uint64_t fdeTableSize;
819
820 /*
821 readelf -e elf32_test | grep .eh_frame_hdr
822 [19] .eh_frame_hdr PROGBITS 00002034 002034 0000dc 00 A 0 0 4
823
824 readelf --debug-dump=frames elf32_test | grep FDE | wc -l
825 26
826
827 readelf -e elf_test | grep .eh_frame_hdr
828 [19] .eh_frame_hdr PROGBITS 0000000000003034 00003034
829
830 readelf --debug-dump=frames elf_test | grep FDE | wc -l
831 22
832 */
833 symbolsFile->GetHDRSectionInfo(ehFrameHdrElfOffset, fdeTableElfOffset, fdeTableSize);
834
835 EXPECT_EQ(ehFrameHdrElfOffset, 0x00003034u);
836 EXPECT_EQ(fdeTableSize, 22U * fdeTableItemSize);
837 }
838
839 /**
840 * @tc.name: GetHDRSectionInfo
841 * @tc.desc:
842 * @tc.type: FUNC
843 */
844 HWTEST_F(SymbolsFileTest, GetHDRSectionInfoStripped, TestSize.Level1)
845 {
846 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(
847 SYMBOL_ELF_FILE, PATH_RESOURCE_TEST_DATA + TEST_FILE_ELF_STRIPPED_NOEFHDR);
848
849 ASSERT_EQ(symbolsFile->LoadDebugInfo(), true);
850
851 uint64_t ehFrameHdrElfOffset;
852 uint64_t fdeTableElfOffset;
853 uint64_t fdeTableSize;
854
855 symbolsFile->GetHDRSectionInfo(ehFrameHdrElfOffset, fdeTableElfOffset, fdeTableSize);
856 uint64_t addr = 0;
857 uint64_t size = 0;
858 uint64_t offset = 0;
859 EXPECT_EQ(symbolsFile->GetSectionInfo(EH_FRAME_HR, addr, size, offset), false);
860 EXPECT_EQ(offset, 0U);
861 EXPECT_EQ(size, 0U);
862 EXPECT_EQ(addr, 0U);
863 }
864 #endif
865
866 /**
867 * @tc.name: CreateSymbolsFile
868 * @tc.desc:
869 * @tc.type: FUNC
870 */
871 HWTEST_F(SymbolsFileTest, CreateSymbolsFile, TestSize.Level1)
872 {
873 EXPECT_NE(SymbolsFile::CreateSymbolsFile(), nullptr);
874 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE), nullptr);
875 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE), nullptr);
876 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE), nullptr);
877 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_JAVA_FILE), nullptr);
878 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_JS_FILE), nullptr);
879 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE), nullptr);
880 EXPECT_NE(SymbolsFile::CreateSymbolsFile(SymbolsFileType(-1)), nullptr);
881 EXPECT_EQ(SymbolsFile::CreateSymbolsFile(SymbolsFileType(-2))->symbolFileType_,
882 SYMBOL_UNKNOW_FILE);
883
884 EXPECT_EQ(SymbolsFile::CreateSymbolsFile(KERNEL_MMAP_NAME)->symbolFileType_,
885 SYMBOL_KERNEL_FILE);
886 EXPECT_EQ(SymbolsFile::CreateSymbolsFile(TEST_FILE_ELF_FULL_PATH)->symbolFileType_,
887 SYMBOL_ELF_FILE);
888 }
889
890 /**
891 * @tc.name: LoadSymbolsFromSaved
892 * @tc.desc:
893 * @tc.type: FUNC
894 */
895 HWTEST_F(SymbolsFileTest, LoadSymbolsFromSaved, TestSize.Level1)
896 {
897 SymbolFileStruct sfs;
898 for (unsigned int type = 0; type < SYMBOL_UNKNOW_FILE; type++) {
899 sfs.filePath_ = std::to_string(rnd_());
900 sfs.symbolType_ = type;
901 sfs.textExecVaddrFileOffset_ = rnd_();
902 sfs.textExecVaddr_ = rnd_();
903 sfs.buildId_ = std::to_string(rnd_());
904 int nameIndex = 0;
905 // after LoadSymbolsFromSaved it will sort from low to high
906 // so we make a order item to test
907 constexpr int rndMax = 10000;
908 std::uniform_int_distribution<int> rndLimi(0, rndMax);
909 sfs.symbolStructs_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
910 std::to_string(nameIndex));
911 nameIndex++;
912 sfs.symbolStructs_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
913 std::to_string(nameIndex));
914 nameIndex++;
915 sfs.symbolStructs_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
916 std::to_string(nameIndex));
917 nameIndex++;
918
919 // setup the min vaddr
920
921 std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::LoadSymbolsFromSaved(sfs);
922
923 EXPECT_EQ(symbolsFile->filePath_, sfs.filePath_);
924 EXPECT_EQ(symbolsFile->symbolFileType_, sfs.symbolType_);
925 EXPECT_EQ(symbolsFile->textExecVaddr_, sfs.textExecVaddr_);
926 EXPECT_EQ(symbolsFile->textExecVaddrFileOffset_, sfs.textExecVaddrFileOffset_);
927 EXPECT_EQ(symbolsFile->GetBuildId(), sfs.buildId_);
928 EXPECT_EQ(symbolsFile->GetSymbols().size(), sfs.symbolStructs_.size());
929
930 for (Symbol symbol : symbolsFile->GetSymbols()) {
931 SymbolStruct symbolStruct = sfs.symbolStructs_.front();
932 EXPECT_EQ(symbol.funcVaddr_, symbolStruct.vaddr_);
933 EXPECT_EQ(symbol.len_, symbolStruct.len_);
934 EXPECT_EQ(symbol.name_, symbolStruct.symbolName_);
935 sfs.symbolStructs_.erase(sfs.symbolStructs_.begin());
936 }
937 }
938 }
939
940 /**
941 * @tc.name: exportSymbolToFileFormatMatched
942 * @tc.desc:
943 * @tc.type: FUNC
944 */
945 HWTEST_F(SymbolsFileTest, exportSymbolToFileFormatMatched, TestSize.Level1)
946 {
947 for (int type = 0; type < SYMBOL_UNKNOW_FILE; type++) {
948 auto symbolsFile = SymbolsFile::CreateSymbolsFile();
949 symbolsFile->filePath_ = std::to_string(rnd_());
950 symbolsFile->symbolFileType_ = static_cast<SymbolsFileType>(type);
951 symbolsFile->textExecVaddrFileOffset_ = rnd_();
952 symbolsFile->buildId_ = std::to_string(rnd_());
953 int nameIndex = 0;
954 // after LoadSymbolsFromSaved it will sort from low to high
955 // so we make a order item to test
956 constexpr int rndMax = 10000;
957 std::uniform_int_distribution<int> rndLimi(0, rndMax);
958 symbolsFile->symbols_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
959 std::to_string(nameIndex), symbolsFile->filePath_);
960 nameIndex++;
961 symbolsFile->symbols_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
962 std::to_string(nameIndex), symbolsFile->filePath_);
963 nameIndex++;
964 symbolsFile->symbols_.emplace_back(rndLimi(rnd_) + nameIndex * rndMax, rnd_(),
965 std::to_string(nameIndex), symbolsFile->filePath_);
966 nameIndex++;
967
968 // setup the min vaddr
969 symbolsFile->textExecVaddr_ = std::numeric_limits<uint64_t>::max();
970
971 for (auto &symbol : symbolsFile->symbols_) {
972 symbolsFile->textExecVaddr_ = std::min(symbol.funcVaddr_, symbolsFile->textExecVaddr_);
973 }
974
975 // access last one to make it as matched.
976 uint64_t matchedVaddr = symbolsFile->symbols_.back().funcVaddr_;
977 auto symbol = symbolsFile->GetSymbolWithVaddr(matchedVaddr);
978 EXPECT_EQ(symbol.funcVaddr_, matchedVaddr);
979 if (HasFailure()) {
980 PrintSymbols(symbolsFile->GetSymbols());
981 }
982
983 SymbolFileStruct sfs {};
984 symbolsFile->ExportSymbolToFileFormat(sfs);
985
986 EXPECT_EQ(symbolsFile->symbolFileType_, sfs.symbolType_);
987 EXPECT_EQ(symbolsFile->textExecVaddrFileOffset_, sfs.textExecVaddrFileOffset_);
988 EXPECT_EQ(symbolsFile->GetBuildId(), sfs.buildId_);
989
990 // matched one should be remove
991 EXPECT_EQ(sfs.symbolStructs_.size(), 1u);
992 for (SymbolStruct symbolStruct : sfs.symbolStructs_) {
993 // nomore found for matched vaddr
994 EXPECT_EQ(symbolStruct.vaddr_, matchedVaddr);
995 }
996 }
997 }
998
999 /**
1000 * @tc.name: UpdateBuildIdIfMatch
1001 * @tc.desc:
1002 * @tc.type: FUNC
1003 */
1004 HWTEST_F(SymbolsFileTest, UpdateBuildIdIfMatch, TestSize.Level1)
1005 {
1006 auto file = SymbolsFile::CreateSymbolsFile();
1007 file->buildId_ = "123";
1008 file->UpdateBuildIdIfMatch("456");
1009 EXPECT_STREQ(file->buildId_.c_str(), "123");
1010 EXPECT_STRNE(file->buildId_.c_str(), "456");
1011 }
1012 } // namespace HiPerf
1013 } // namespace Developtools
1014 } // namespace OHOS