• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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  * Description: KernelSymbolsParser class implements
16  */
17 #include "kernel_symbols_parser.h"
18 #include "file_utils.h"
19 #include "logging.h"
20 #include "string_utils.h"
21 
22 #include <algorithm> // for std::sort
23 #include <sstream>   // for std::stringstream
24 
25 namespace {
26 constexpr int ADDR_VALUE_BASE = 16;
27 constexpr int MAX_BUFFER_SIZE = 10 * 1000;
28 } // namespace
29 
30 FTRACE_NS_BEGIN
KernelSymbolsParser()31 KernelSymbolsParser::KernelSymbolsParser()
32 {
33     PROFILER_LOG_INFO(LOG_CORE, "KernelSymbolsParser create!");
34 }
35 
~KernelSymbolsParser()36 KernelSymbolsParser::~KernelSymbolsParser()
37 {
38     PROFILER_LOG_INFO(LOG_CORE, "KernelSymbolsParser destroy!");
39 }
40 
Accept(const std::function<void (const KernelSymbol &)> & visitor)41 void KernelSymbolsParser::Accept(const std::function<void(const KernelSymbol&)>& visitor)
42 {
43     std::for_each(kernelSymbols_.begin(), kernelSymbols_.end(), visitor);
44 }
45 
IsValidTextSymbol(const KernelSymbol & a)46 bool KernelSymbolsParser::IsValidTextSymbol(const KernelSymbol& a)
47 {
48     if (a.addr == 0 || a.name.empty()) {
49         return false;
50     }
51     if (a.name[0] == '$') {
52         return false;
53     }
54     if (a.type != 't' && a.type != 'T') {
55         return false;
56     }
57     return true;
58 }
59 
CompareSymbolInfo(const KernelSymbol & a,const KernelSymbol & b)60 bool KernelSymbolsParser::CompareSymbolInfo(const KernelSymbol& a, const KernelSymbol& b)
61 {
62     if (a.addr != b.addr) {
63         return a.addr < b.addr;
64     }
65     if (a.name != b.name) {
66         return a.name < b.name;
67     }
68     return a.type < b.type;
69 }
70 
Parse(const std::string & kallsyms)71 bool KernelSymbolsParser::Parse(const std::string& kallsyms)
72 {
73     CHECK_TRUE(!kallsyms.empty(), false, "kallsyms is empty!");
74     std::stringstream sin(kallsyms);
75     std::string line;
76     KernelSymbol info;
77     std::string addrStr;
78     std::stringstream ss;
79     int count = 0;
80     while (std::getline(sin, line)) {
81         // one of following format:
82         // c0109b3c T arm_elf_read_implies_exec
83         // bf004fd8 t media_mem_init       [hi_osal]
84         ss.clear();
85         ss.str(line);
86         if (ss >> addrStr >> info.type >> info.name) {
87             info.addr = strtoull(addrStr.c_str(), nullptr, ADDR_VALUE_BASE);
88         }
89         if (info.addr == 0) {
90             continue;
91         }
92         if (StringUtils::EndsWith(info.name, ".cfi")) {
93             info.name = info.name.substr(0, info.name.size() - (sizeof(".cfi") - 1));
94         }
95         if (IsValidTextSymbol(info)) {
96             if (count % MAX_BUFFER_SIZE == 0) {
97                 kernelSymbols_.resize(kernelSymbols_.size() + MAX_BUFFER_SIZE);
98             }
99             kernelSymbols_[count] = info;
100             count++;
101         }
102     }
103 
104     kernelSymbols_.resize(count);
105     std::sort(kernelSymbols_.begin(), kernelSymbols_.end(), CompareSymbolInfo);
106     return kernelSymbols_.size();
107 }
108 FTRACE_NS_END
109