• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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