• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "kernel_symbol_info.h"
16 
17 #include <cstring>
18 #include <fstream>
19 #include <sstream>
20 
21 namespace OHOS {
22 namespace Developtools {
23 namespace Hiebpf {
GetSymbol(const std::string & line,SymbolItem & symbol)24 void KernelSymbolInfo::GetSymbol(const std::string &line, SymbolItem &symbol)
25 {
26     std::stringstream str(line.c_str());
27     str >> std::hex >> symbol.value_;
28     str >> symbol.type_;
29     // only keep text or weak type
30     if (std::strchr("TtWw", symbol.type_)) {
31         symbol.type_ = 'T';
32     } else {
33         return;
34     }
35     str >> symbol.name_;
36 }
37 
GetBinary(const std::vector<SymbolItem> & symbolItems,uint64_t vaddrStart,uint64_t vaddrEnd,uint32_t strTabLen,std::vector<uint8_t> & buf)38 void KernelSymbolInfo::GetBinary(const std::vector<SymbolItem> &symbolItems,
39                                  uint64_t vaddrStart,
40                                  uint64_t vaddrEnd,
41                                  uint32_t strTabLen,
42                                  std::vector<uint8_t> &buf)
43 {
44     // (value + size + nameOffset)
45     uint32_t symTabLen = (sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t)) *
46                          symbolItems.size();
47     // vaddrStart + vaddrEnd + symTbaLen + strTabLen + symTabData + strTabData
48     uint32_t dataLen = sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t)
49                        + symTabLen + strTabLen;
50     buf.resize(dataLen);
51 
52     uint8_t *p = buf.data();
53     *(reinterpret_cast<uint64_t *>(p)) = vaddrStart;
54     p += sizeof(uint64_t);
55     *(reinterpret_cast<uint64_t *>(p)) = vaddrEnd;
56     p += sizeof(uint64_t);
57     *(reinterpret_cast<uint32_t *>(p)) = symTabLen;
58     p += sizeof(uint32_t);
59     *(reinterpret_cast<uint32_t *>(p)) = strTabLen;
60     p += sizeof(uint32_t);
61 
62     uint32_t strTabSize = 0;
63     uint8_t *pStrTab = p + symTabLen;
64     for (auto &symbol : symbolItems) {
65         *(reinterpret_cast<uint64_t *>(p)) = symbol.value_;
66         p += sizeof(uint64_t);
67         *(reinterpret_cast<uint32_t *>(p)) = symbol.size_;
68         p += sizeof(uint32_t);
69         *(reinterpret_cast<uint32_t *>(p)) = strTabSize;
70         p += sizeof(uint32_t);
71 
72         std::copy(symbol.name_.c_str(),
73                   symbol.name_.c_str() + symbol.name_.size() + 1,
74                   pStrTab + strTabSize);
75         strTabSize += symbol.name_.size() + 1;
76     }
77 }
78 
GetSymbolData(std::vector<uint8_t> & buf)79 uint32_t KernelSymbolInfo::GetSymbolData(std::vector<uint8_t> &buf)
80 {
81     buf.clear();
82     buf.reserve(DEFAULT_BUFF_SIZE);
83 
84     std::ifstream file(KALLSYMS_PATH);
85     std::string line;
86     std::getline(file, line);
87     SymbolItem prevSymbol;
88     GetSymbol(line, prevSymbol);
89     uint64_t vaddrStart = prevSymbol.value_;
90 
91     std::vector<SymbolItem> symbolItems;
92     uint32_t strTabLen = 0;
93     SymbolItem currSymbol;
94     while (std::getline(file, line)) {
95         GetSymbol(line, currSymbol);
96         if (prevSymbol.value_ >= currSymbol.value_) {
97             continue; // duplicated or wrong
98         }
99         if (prevSymbol.type_ == 'T') {
100             prevSymbol.size_ = currSymbol.value_ - prevSymbol.value_;
101             symbolItems.emplace_back(prevSymbol);
102             strTabLen += prevSymbol.name_.size() + 1;
103         }
104         prevSymbol = currSymbol;
105     }
106     file.close();
107     if (prevSymbol.type_ == 'T') {
108         symbolItems.emplace_back(prevSymbol);
109         strTabLen += prevSymbol.name_.size() + 1;
110     }
111     if (symbolItems.empty()) {
112         return 0;
113     }
114 
115     uint64_t vaddrEnd = prevSymbol.value_ + prevSymbol.size_;
116     GetBinary(symbolItems, vaddrStart, vaddrEnd, strTabLen, buf);
117     return buf.size();
118 }
119 } // namespace Hiebpf
120 } // namespace Developtools
121 } // namespace OHOS