1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 #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