1 /*
2 * Copyright (c) 2021 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 "ebpf_data_reader.h"
17 #include "file_system_data_parser.h"
18 #include "string_help.h"
19
20 namespace SysTuning {
21 namespace TraceStreamer {
22 using namespace SysTuning::base;
23 using namespace SysTuning::EbpfStdtype;
EbpfDataReader(TraceDataCache * dataCache,const TraceStreamerFilters * filter)24 EbpfDataReader::EbpfDataReader(TraceDataCache* dataCache, const TraceStreamerFilters* filter)
25 : EventParserBase(dataCache, filter),
26 pidAndStartAddrToMapsAddr_(nullptr),
27 elfAddrAndStValueToSymAddr_(nullptr),
28 tracerEventToStrIndex_(INVALID_UINT64)
29 {
30 }
InitEbpfData(const std::deque<uint8_t> & dequeBuffer,uint64_t size)31 bool EbpfDataReader::InitEbpfData(const std::deque<uint8_t>& dequeBuffer, uint64_t size)
32 {
33 buffer_ = std::make_unique<uint8_t[]>(size);
34 std::copy(dequeBuffer.begin(), dequeBuffer.begin() + size, buffer_.get());
35
36 startAddr_ = buffer_.get();
37 bufferSize_ = size;
38 unresolvedLen_ = size;
39 if (!InitEbpfHeader() || !ReadEbpfData()) {
40 return false;
41 }
42 return true;
43 }
44
InitEbpfHeader()45 bool EbpfDataReader::InitEbpfHeader()
46 {
47 if (bufferSize_ < EbpfDataHeader::EBPF_DATA_HEADER_SIZE) {
48 TS_LOGE("buffer size less than ebpf data header!!!, bufferSize_ = %lu ", bufferSize_);
49 return false;
50 }
51 ebpfDataHeader_ = reinterpret_cast<EbpfDataHeader*>(startAddr_);
52
53 if (ebpfDataHeader_->header.magic != EbpfDataHeader::HEADER_MAGIC) {
54 TS_LOGE("Get EBPF file header failed! magic = %lx", ebpfDataHeader_->header.magic);
55 return false;
56 }
57 if (ebpfDataHeader_->header.headSize != EbpfDataHeader::EBPF_DATA_HEADER_SIZE) {
58 TS_LOGE("Get ebpf file header failed! headSize = %u", ebpfDataHeader_->header.headSize);
59 return false;
60 }
61 TS_LOGI("EBPF data header : magic = %llx, headSize = %llu, clock = %llu, cmdline = %s",
62 ebpfDataHeader_->header.magic, ebpfDataHeader_->header.headSize, ebpfDataHeader_->header.clock,
63 ebpfDataHeader_->cmdline);
64 startAddr_ += EbpfDataHeader::EBPF_DATA_HEADER_SIZE;
65 unresolvedLen_ -= EbpfDataHeader::EBPF_DATA_HEADER_SIZE;
66 return true;
67 }
68
ReadEbpfData()69 bool EbpfDataReader::ReadEbpfData()
70 {
71 EbpfTypeAndLength* dataTitle;
72 while (unresolvedLen_ > EBPF_TITLE_SIZE) {
73 dataTitle = reinterpret_cast<EbpfTypeAndLength*>(startAddr_);
74 startAddr_ += EBPF_TITLE_SIZE;
75 unresolvedLen_ -= EBPF_TITLE_SIZE;
76 if (dataTitle->length > unresolvedLen_) {
77 TS_LOGE("Get EBPF data Title failed!");
78 TS_LOGE("type = %lx, length = %lx", dataTitle->type, dataTitle->length);
79 return false;
80 }
81 if (dataTitle->length == 0) {
82 continue;
83 }
84
85 bool ret = true;
86 switch (dataTitle->type) {
87 case ITEM_EVENT_MAPS: {
88 ret = ReadItemEventMaps(startAddr_, dataTitle->length);
89 break;
90 }
91 case ITEM_SYMBOL_INFO: {
92 ret = ReadItemSymbolInfo(startAddr_, dataTitle->length);
93 break;
94 }
95 case ITEM_EVENT_FS: {
96 ret = ReadItemEventFs(startAddr_, dataTitle->length);
97 break;
98 }
99 case ITEM_EVENT_VM: {
100 ret = ReadItemEventPagedMemory(startAddr_, dataTitle->length);
101 break;
102 }
103 case ITEM_EVENT_BIO: {
104 ret = ReadItemEventBIO(startAddr_, dataTitle->length);
105 break;
106 }
107 case ITEM_EVENT_STR: {
108 ret = ReadItemEventStr(startAddr_, dataTitle->length);
109 break;
110 }
111 default:
112 TS_LOGI("Do not support EBPF type: %d, length: %d", dataTitle->type, dataTitle->length);
113 }
114 if (!ret) {
115 return false;
116 }
117 startAddr_ += dataTitle->length;
118 unresolvedLen_ -= dataTitle->length;
119 }
120 return true;
121 }
122
ReadItemEventMaps(const uint8_t * buffer,uint32_t size)123 bool EbpfDataReader::ReadItemEventMaps(const uint8_t* buffer, uint32_t size)
124 {
125 if (size < sizeof(MapsFixedHeader)) {
126 TS_LOGE("get maps addr Failed!!!");
127 return false;
128 }
129 auto procMapsAddr = reinterpret_cast<const MapsFixedHeader*>(buffer);
130 pidAndStartAddrToMapsAddr_.Insert(procMapsAddr->pid, procMapsAddr->start, procMapsAddr);
131 #if WITH_EBPF_HELP
132 if ((procMapsAddr->fileNameLen > size - sizeof(MapsFixedHeader)) || !procMapsAddr->fileNameLen) {
133 TS_LOGE("maps fileNameLen error!!!");
134 return false;
135 }
136 auto fileNameAddr = const_cast<char*>(reinterpret_cast<const char*>(procMapsAddr + 1));
137 fileNameAddr[procMapsAddr->fileNameLen - 1] = '\0';
138 auto fileNameIndex = traceDataCache_->GetDataIndex(fileNameAddr);
139
140 // add proc Maps Data
141 traceDataCache_->GetEbpfProcessMaps()->AppendNewData(procMapsAddr->start, procMapsAddr->end, procMapsAddr->offset,
142 procMapsAddr->pid, procMapsAddr->fileNameLen, fileNameIndex);
143 #endif
144 return true;
145 }
UpdateElfAddrAndStValueToSymAddrMap(const ElfEventFixedHeader * elfAddr,uint32_t size)146 void EbpfDataReader::UpdateElfAddrAndStValueToSymAddrMap(const ElfEventFixedHeader* elfAddr, uint32_t size)
147 {
148 if (size < sizeof(ElfEventFixedHeader) + elfAddr->strTabLen + elfAddr->symTabLen + elfAddr->fileNameLen) {
149 TS_LOGE("elf addr size error!!!");
150 return;
151 }
152 auto symEntLen = elfAddr->symEntLen;
153 auto symTabHeadAddr = reinterpret_cast<const uint8_t*>(elfAddr + 1) + elfAddr->strTabLen;
154 if (symEntLen == ELF32_SYM) {
155 auto firstSymbolAddr = reinterpret_cast<const Elf32_Sym*>(symTabHeadAddr);
156 for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) {
157 auto symAddr = firstSymbolAddr + i;
158 if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) {
159 elfAddrAndStValueToSymAddr_.Insert(elfAddr, symAddr->st_value,
160 reinterpret_cast<const uint8_t*>(symAddr));
161 }
162 }
163 } else {
164 auto firstSymbolAddr = reinterpret_cast<const Elf64_Sym*>(symTabHeadAddr);
165 for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) {
166 auto symAddr = firstSymbolAddr + i;
167 if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) {
168 elfAddrAndStValueToSymAddr_.Insert(elfAddr, symAddr->st_value,
169 reinterpret_cast<const uint8_t*>(symAddr));
170 }
171 }
172 }
173 }
174
UpdateElfPathIndexToElfAddrMap(const ElfEventFixedHeader * elfAddr,uint32_t size)175 void EbpfDataReader::UpdateElfPathIndexToElfAddrMap(const ElfEventFixedHeader* elfAddr, uint32_t size)
176 {
177 if ((elfAddr->fileNameLen > size - sizeof(ElfEventFixedHeader) - elfAddr->strTabLen - elfAddr->symTabLen) ||
178 !elfAddr->fileNameLen) {
179 TS_LOGE("elf filename len is error!!!");
180 return;
181 }
182
183 uint64_t fileNameIndex = INVALID_UINT64;
184 auto fileNameAddr = const_cast<char*>(reinterpret_cast<const char*>(
185 reinterpret_cast<const uint8_t*>(elfAddr + 1) + elfAddr->strTabLen + elfAddr->symTabLen));
186 fileNameAddr[elfAddr->fileNameLen - 1] = '\0';
187 fileNameIndex = traceDataCache_->GetDataIndex(fileNameAddr);
188 elfPathIndexToElfFixedHeaderAddr_.insert(std::make_pair(fileNameIndex, elfAddr));
189
190 #if WITH_EBPF_HELP
191 // add Elf symbol Data
192 traceDataCache_->GetEbpfElf()->AppendNewData(elfId_, elfAddr->textVaddr, elfAddr->textOffset, elfAddr->strTabLen,
193 elfAddr->symTabLen, elfAddr->fileNameLen, elfAddr->symEntLen,
194 fileNameIndex);
195 #endif
196 }
197
198 #if WITH_EBPF_HELP
UpdateEbpfElfSymbolTable(const ElfEventFixedHeader * elfAddr,uint32_t size)199 void EbpfDataReader::UpdateEbpfElfSymbolTable(const ElfEventFixedHeader* elfAddr, uint32_t size)
200 {
201 if (size < sizeof(ElfEventFixedHeader) + elfAddr->strTabLen + elfAddr->symTabLen + elfAddr->fileNameLen) {
202 TS_LOGE("elf addr size error!!!");
203 return;
204 }
205 auto symEntLen = elfAddr->symEntLen;
206 if (symEntLen == ELF32_SYM) {
207 auto firstSymbolAddr =
208 reinterpret_cast<const Elf32_Sym*>(reinterpret_cast<const uint8_t*>(elfAddr + 1) + elfAddr->strTabLen);
209 for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) {
210 auto symAddr = firstSymbolAddr + i;
211 if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) {
212 traceDataCache_->GetEbpfElfSymbol()->AppendNewData(elfId_, symAddr->st_name, symAddr->st_value,
213 symAddr->st_size);
214 }
215 }
216 } else {
217 auto firstSymbolAddr =
218 reinterpret_cast<const Elf64_Sym*>(reinterpret_cast<const uint8_t*>(elfAddr + 1) + elfAddr->strTabLen);
219 for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) {
220 auto symAddr = firstSymbolAddr + i;
221 if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) {
222 traceDataCache_->GetEbpfElfSymbol()->AppendNewData(elfId_, symAddr->st_name, symAddr->st_value,
223 symAddr->st_size);
224 }
225 }
226 }
227 }
228 #endif
229
ReadItemSymbolInfo(const uint8_t * buffer,uint32_t size)230 bool EbpfDataReader::ReadItemSymbolInfo(const uint8_t* buffer, uint32_t size)
231 {
232 if (size < sizeof(ElfEventFixedHeader)) {
233 TS_LOGE("get symbol addr failed!!!");
234 return false;
235 }
236 auto elfAddr = reinterpret_cast<const ElfEventFixedHeader*>(buffer);
237 UpdateElfAddrAndStValueToSymAddrMap(elfAddr, size);
238 UpdateElfPathIndexToElfAddrMap(elfAddr, size);
239 #if WITH_EBPF_HELP
240 UpdateEbpfElfSymbolTable(elfAddr, size);
241 elfId_++;
242 #endif
243 return true;
244 }
245
ReadItemEventFs(const uint8_t * buffer,uint32_t size)246 bool EbpfDataReader::ReadItemEventFs(const uint8_t* buffer, uint32_t size)
247 {
248 if (size < sizeof(FsFixedHeader)) {
249 TS_LOGE("get file system event addr failed!!!");
250 return false;
251 }
252 auto fsFixedHeaderAddr = reinterpret_cast<const FsFixedHeader*>(buffer);
253 endTsToFsFixedHeader_.insert(std::make_pair(fsFixedHeaderAddr->endTime, fsFixedHeaderAddr));
254 return true;
255 }
256
ReadItemEventPagedMemory(const uint8_t * buffer,uint32_t size)257 bool EbpfDataReader::ReadItemEventPagedMemory(const uint8_t* buffer, uint32_t size)
258 {
259 if (size < sizeof(PagedMemoryFixedHeader)) {
260 TS_LOGE("get page memory event addr failed!!!");
261 return false;
262 }
263 auto pagedMemoryFixedHeaderAddr = reinterpret_cast<const PagedMemoryFixedHeader*>(buffer);
264 endTsToPagedMemoryFixedHeader_.insert(std::make_pair(pagedMemoryFixedHeaderAddr->endTime,
265 pagedMemoryFixedHeaderAddr));
266 return true;
267 }
268
ReadItemEventBIO(const uint8_t * buffer,uint32_t size)269 bool EbpfDataReader::ReadItemEventBIO(const uint8_t* buffer, uint32_t size)
270 {
271 if (size < sizeof(BIOFixedHeader)) {
272 TS_LOGE("get Block IO event addr failed!!!");
273 return false;
274 }
275 auto bioFixedHeaderAddr = reinterpret_cast<const BIOFixedHeader*>(buffer);
276 endTsToBIOFixedHeader_.insert(std::make_pair(bioFixedHeaderAddr->endTime, bioFixedHeaderAddr));
277 return true;
278 }
279
ReadItemEventStr(const uint8_t * buffer,uint32_t size)280 bool EbpfDataReader::ReadItemEventStr(const uint8_t* buffer, uint32_t size)
281 {
282 if (size < sizeof(StrEventFixedHeader)) {
283 TS_LOGE("get str event addr failed!!!");
284 return false;
285 }
286 auto strFixedHeaderAddr = reinterpret_cast<const StrEventFixedHeader*>(buffer);
287 auto itid =
288 streamFilters_->processFilter_->GetOrCreateThreadWithPid(strFixedHeaderAddr->tid, strFixedHeaderAddr->pid);
289 auto strAddr = const_cast<char*>(reinterpret_cast<const char*>(strFixedHeaderAddr + 1));
290 if ((strFixedHeaderAddr->strLen > size - sizeof(StrEventFixedHeader)) || !strFixedHeaderAddr->strLen) {
291 TS_LOGE("invalid str event, strEventFixedHeader = %d, strlen = %d, size = %d",
292 sizeof(StrEventFixedHeader), strFixedHeaderAddr->strLen, size);
293 return true;
294 }
295 strAddr[strFixedHeaderAddr->strLen - 1] = '\0';
296 auto strIndex = traceDataCache_->GetDataIndex(strAddr);
297 tracerEventToStrIndex_.Insert(strFixedHeaderAddr->srcTracer, strFixedHeaderAddr->srcType, itid,
298 strFixedHeaderAddr->startTime, strIndex);
299 return true;
300 }
301
GetTracerEventToStrIndexMap()302 QuatraMap<uint32_t, uint32_t, uint32_t, uint64_t, DataIndex>& EbpfDataReader::GetTracerEventToStrIndexMap()
303 {
304 return tracerEventToStrIndex_;
305 }
306
GetPidAndStartAddrToMapsAddr() const307 const DoubleMap<uint32_t, uint64_t, const MapsFixedHeader*>& EbpfDataReader::GetPidAndStartAddrToMapsAddr() const
308 {
309 return pidAndStartAddrToMapsAddr_;
310 }
311
312 const DoubleMap<const ElfEventFixedHeader*, uint64_t, const uint8_t*>&
GetElfAddrAndStartValueToSymAddr() const313 EbpfDataReader::GetElfAddrAndStartValueToSymAddr() const
314 {
315 return elfAddrAndStValueToSymAddr_;
316 }
317
GetFileSystemEventMap() const318 const std::multimap<uint64_t, const FsFixedHeader*>& EbpfDataReader::GetFileSystemEventMap() const
319 {
320 return endTsToFsFixedHeader_;
321 }
322
GetPagedMemoryMap() const323 const std::multimap<uint64_t, const PagedMemoryFixedHeader*>& EbpfDataReader::GetPagedMemoryMap() const
324 {
325 return endTsToPagedMemoryFixedHeader_;
326 }
327
GetBIOSampleMap() const328 const std::multimap<uint64_t, const BIOFixedHeader*>& EbpfDataReader::GetBIOSampleMap() const
329 {
330 return endTsToBIOFixedHeader_;
331 }
332
GetElfPathIndexToElfAddr() const333 const std::map<DataIndex, const ElfEventFixedHeader*>& EbpfDataReader::GetElfPathIndexToElfAddr() const
334 {
335 return elfPathIndexToElfFixedHeaderAddr_;
336 }
GetEbpfDataHeader() const337 const EbpfDataHeader* EbpfDataReader::GetEbpfDataHeader() const
338 {
339 return const_cast<const EbpfDataHeader*>(ebpfDataHeader_);
340 }
341 } // namespace TraceStreamer
342 } // namespace SysTuning
343