• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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 
16 #include "pbreader_parser.h"
17 #include <unistd.h>
18 #include "app_start_filter.h"
19 #include "binder_filter.h"
20 #include "common_types.pbreader.h"
21 #include "cpu_filter.h"
22 #include "data_area.h"
23 #ifdef ENABLE_HTRACE
24 #include "ftrace_event.pbreader.h"
25 #include "trace_plugin_result.pbreader.h"
26 #endif
27 #ifdef ENABLE_MEMORY
28 #include "memory_plugin_result.pbreader.h"
29 #endif
30 #include "stat_filter.h"
31 #if IS_WASM
32 #include "wasm_func.h"
33 #endif
34 namespace SysTuning {
35 namespace TraceStreamer {
PbreaderParser(TraceDataCache * dataCache,const TraceStreamerFilters * filters)36 PbreaderParser::PbreaderParser(TraceDataCache *dataCache, const TraceStreamerFilters *filters)
37     : ParserBase(filters),
38       pbreaderClockDetailParser_(std::make_unique<PbreaderClockDetailParser>(dataCache, filters)),
39 #ifdef ENABLE_HTRACE
40       htraceCpuDetailParser_(std::make_unique<HtraceCpuDetailParser>(dataCache, filters)),
41       htraceSymbolsDetailParser_(std::make_unique<HtraceSymbolsDetailParser>(dataCache, filters)),
42 #endif
43 #ifdef ENABLE_FFRT
44       pbreaderFfrtParser_(
45           std::make_unique<PbreaderFfrtDetailParser>(dataCache, filters, htraceCpuDetailParser_->eventParser_.get())),
46 #endif
47 #ifdef ENABLE_MEMORY
48       pbreaderMemParser_(std::make_unique<PbreaderMemParser>(dataCache, filters)),
49 #endif
50 #ifdef ENABLE_HILOG
51       pbreaderHiLogParser_(std::make_unique<PbreaderHiLogParser>(dataCache, filters)),
52 #endif
53 #ifdef ENABLE_NATIVE_HOOK
54       pbreaderNativeHookParser_(std::make_unique<PbreaderNativeHookParser>(dataCache, filters)),
55 #endif
56 #ifdef ENABLE_HTDUMP
57       pbreaderHidumpParser_(std::make_unique<PbreaderHidumpParser>(dataCache, filters)),
58 #endif
59 #ifdef ENABLE_CPUDATA
60       cpuUsageParser_(std::make_unique<PbreaderCpuDataParser>(dataCache, filters)),
61 #endif
62 #ifdef ENABLE_NETWORK
63       networkParser_(std::make_unique<PbreaderNetworkParser>(dataCache, filters)),
64 #endif
65 #ifdef ENABLE_DISKIO
66       diskIOParser_(std::make_unique<PbreaderDiskIOParser>(dataCache, filters)),
67 #endif
68 #ifdef ENABLE_PROCESS
69       processParser_(std::make_unique<PbreaderProcessParser>(dataCache, filters)),
70 #endif
71 #ifdef ENABLE_HISYSEVENT
72       hisyseventParser_(std::make_unique<PbreaderHisyseventParser>(dataCache, filters)),
73 #endif
74 #ifdef ENABLE_ARKTS
75       jsMemoryParser_(std::make_unique<PbreaderJSMemoryParser>(dataCache, filters)),
76 #endif
77 #ifdef ENABLE_HIPERF
78       perfDataParser_(std::make_unique<PerfDataParser>(dataCache, filters)),
79 #endif
80 #ifdef ENABLE_EBPF
81       ebpfDataParser_(std::make_unique<EbpfDataParser>(dataCache, filters)),
82 #endif
83 #ifdef ENABLE_XPOWER
84       xpowerParser_(std::make_unique<PbreaderXpowerParser>(dataCache, filters)),
85 #endif
86 #ifdef ENABLE_STREAM_EXTEND
87       pbreaderStreamParser_(std::make_unique<PbreaderStreamParser>(dataCache, filters)),
88 #endif
89       traceDataCache_(dataCache)
90 {
91     InitPluginNameIndex();
92     if (traceDataCache_->supportThread_) {
93         dataSegArray_ = std::make_unique<PbreaderDataSegment[]>(maxSegArraySize);
94     } else {
95         dataSegArray_ = std::make_unique<PbreaderDataSegment[]>(1);
96     }
97 }
InitHookPluginNameIndex()98 inline void PbreaderParser::InitHookPluginNameIndex()
99 {
100 #ifdef ENABLE_NATIVE_HOOK
101     nativeHookPluginIndex_.insert(traceDataCache_->GetDataIndex("nativehook"));
102     nativeHookPluginIndex_.insert(traceDataCache_->GetDataIndex("hookdaemon"));
103     nativeHookConfigIndex_ = traceDataCache_->GetDataIndex("nativehook_config");
104     supportPluginNameIndex_.insert(nativeHookPluginIndex_.begin(), nativeHookPluginIndex_.end());
105     supportPluginNameIndex_.insert(nativeHookConfigIndex_);
106 #endif
107 }
InitMemoryPluginNameIndex()108 inline void PbreaderParser::InitMemoryPluginNameIndex()
109 {
110 #ifdef ENABLE_MEMORY
111     memPluginIndex_ = traceDataCache_->GetDataIndex("memory-plugin");
112     memoryPluginConfigIndex_ = traceDataCache_->GetDataIndex("memory-plugin_config");
113     supportPluginNameIndex_.insert(memPluginIndex_);
114     supportPluginNameIndex_.insert(memoryPluginConfigIndex_);
115 #endif
116 }
InitHiPluginNameIndex()117 inline void PbreaderParser::InitHiPluginNameIndex()
118 {
119 #ifdef ENABLE_HTDUMP
120     hidumpPluginIndex_.insert(traceDataCache_->GetDataIndex("hidump-plugin"));
121     hidumpPluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libhidumpplugin.z.so"));
122     supportPluginNameIndex_.insert(hidumpPluginIndex_.begin(), hidumpPluginIndex_.end());
123 #endif
124 #ifdef ENABLE_HILOG
125     hilogPluginIndex_.insert(traceDataCache_->GetDataIndex("hilog-plugin"));
126     hilogPluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libhilogplugin.z.so"));
127     supportPluginNameIndex_.insert(hilogPluginIndex_.begin(), hilogPluginIndex_.end());
128 #endif
129 #ifdef ENABLE_HISYSEVENT
130     hisyseventPluginIndex_ = traceDataCache_->GetDataIndex("hisysevent-plugin");
131     hisyseventPluginConfigIndex_ = traceDataCache_->GetDataIndex("hisysevent-plugin_config");
132     supportPluginNameIndex_.insert(hisyseventPluginIndex_);
133     supportPluginNameIndex_.insert(hisyseventPluginConfigIndex_);
134 #endif
135 }
InitPluginNameIndex()136 void PbreaderParser::InitPluginNameIndex()
137 {
138 #ifdef ENABLE_PROCESS
139     processPluginIndex_ = traceDataCache_->GetDataIndex("process-plugin");
140     supportPluginNameIndex_.insert(processPluginIndex_);
141 #endif
142 #ifdef ENABLE_DISKIO
143     diskioPluginIndex_ = traceDataCache_->GetDataIndex("diskio-plugin");
144     supportPluginNameIndex_.insert(diskioPluginIndex_);
145 #endif
146     InitMemoryPluginNameIndex();
147     InitHiPluginNameIndex();
148 #ifdef ENABLE_CPUDATA
149     cpuPluginIndex_ = traceDataCache_->GetDataIndex("cpu-plugin");
150     supportPluginNameIndex_.insert(cpuPluginIndex_);
151 #endif
152 #ifdef ENABLE_NETWORK
153     networkPluginIndex_ = traceDataCache_->GetDataIndex("network-plugin");
154     supportPluginNameIndex_.insert(networkPluginIndex_);
155 #endif
156     InitHookPluginNameIndex();
157 #ifdef ENABLE_ARKTS
158     arktsPluginIndex_ = traceDataCache_->GetDataIndex("arkts-plugin");
159     arktsPluginConfigIndex_ = traceDataCache_->GetDataIndex("arkts-plugin_config");
160     supportPluginNameIndex_.insert(arktsPluginIndex_);
161     supportPluginNameIndex_.insert(arktsPluginConfigIndex_);
162 #endif
163 #ifdef ENABLE_HTRACE
164     ftracePluginIndex_.insert(traceDataCache_->GetDataIndex("ftrace-plugin"));
165     ftracePluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libftrace_plugin.z.so"));
166     supportPluginNameIndex_.insert(ftracePluginIndex_.begin(), ftracePluginIndex_.end());
167 #endif
168 #ifdef ENABLE_FFRT
169     ffrtPluginIndex_ = traceDataCache_->GetDataIndex("ffrt-profiler");
170     ffrtPluginConfigIndex_ = traceDataCache_->GetDataIndex("ffrt-profiler_config");
171     supportPluginNameIndex_.insert(ffrtPluginIndex_);
172     supportPluginNameIndex_.insert(ffrtPluginConfigIndex_);
173 #endif
174 #ifdef ENABLE_STREAM_EXTEND
175     streamPluginIndex_ = traceDataCache_->GetDataIndex("stream-plugin");
176     supportPluginNameIndex_.insert(streamPluginIndex_);
177 #endif
178 #ifdef ENABLE_XPOWER
179     xpowerPluginIndex_ = traceDataCache_->GetDataIndex("xpower-plugin");
180     supportPluginNameIndex_.insert(xpowerPluginIndex_);
181 #endif
182 }
183 
184 #if defined(ENABLE_HIPERF) || defined(ENABLE_NATIVE_HOOK) || defined(ENABLE_EBPF)
ParseELF(const std::string & directory,const std::string & fileName)185 std::unique_ptr<SymbolsFile> PbreaderParser::ParseELF(const std::string &directory, const std::string &fileName)
186 {
187     auto symbolsFile = OHOS::Developtools::HiPerf::SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, fileName);
188     if (!symbolsFile) {
189         return nullptr;
190     }
191     symbolsFile->setSymbolsFilePath(directory);
192     if (!symbolsFile->LoadSymbols(nullptr, fileName)) {
193         return nullptr;
194     }
195     return symbolsFile;
196 }
197 #endif
198 
~PbreaderParser()199 PbreaderParser::~PbreaderParser()
200 {
201     TS_LOGI("clockid 2 is for RealTime and 1 is for BootTime");
202 }
203 
ReparseSymbolFileAndResymbolization(const std::string & directory,const std::string & fileName)204 bool PbreaderParser::ReparseSymbolFileAndResymbolization(const std::string &directory, const std::string &fileName)
205 {
206     auto parseStatus = false;
207 #if defined(ENABLE_HIPERF) || defined(ENABLE_NATIVE_HOOK) || defined(ENABLE_EBPF)
208     auto symbolsFile = ParseELF(directory, fileName);
209 #endif
210 #ifdef ENABLE_HIPERF
211     if (traceDataCache_->GetPerfFilesData()->Size() > 0) {
212         perfDataParser_->PerfReloadSymbolFile(symbolsFile);
213 #ifdef ENABLE_ADDR2LINE
214         perfDataParser_->ParseSourceLocation(directory, fileName);
215 #endif
216         parseStatus = true;
217     }
218 #endif
219 #ifdef ENABLE_NATIVE_HOOK
220     if (traceDataCache_->GetNativeHookFrameData()->Size() > 0) {
221         pbreaderNativeHookParser_->NativeHookReloadElfSymbolTable(symbolsFile);
222         parseStatus = true;
223     }
224 #endif
225 #ifdef ENABLE_EBPF
226     if (traceDataCache_->GetEbpfCallStack()->Size() > 0) {
227         ebpfDataParser_->EBPFReloadElfSymbolTable(symbolsFile);
228         parseStatus = true;
229     }
230 #endif
231     return parseStatus;
232 }
233 
WaitForHPluginParserEnd()234 inline void PbreaderParser::WaitForHPluginParserEnd()
235 {
236 #ifdef ENABLE_HTRACE
237     htraceCpuDetailParser_->FilterAllEvents();
238     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE,
239                                                                       dataSourceTypeTraceClockid_);
240 #endif
241 #ifdef ENABLE_HILOG
242     pbreaderHiLogParser_->Finish();
243     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HILOG,
244                                                                       dataSourceTypeHilogClockid_);
245 #endif
246 #ifdef ENABLE_HTDUMP
247     pbreaderHidumpParser_->Finish();
248     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_FPS, dataSourceTypeFpsClockid_);
249 #endif
250 #ifdef ENABLE_HISYSEVENT
251     hisyseventParser_->Finish();
252     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HISYSEVENT,
253                                                                       dataSourceTypeHisyseventClockid_);
254 #endif
255 }
256 
WaitForOtherPluginParserEnd()257 inline void PbreaderParser::WaitForOtherPluginParserEnd()
258 {
259 #ifdef ENABLE_NATIVE_HOOK
260     pbreaderNativeHookParser_->FinishParseNativeHookData();
261     pbreaderNativeHookParser_->Finish();
262     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NATIVEHOOK,
263                                                                       dataSourceTypeNativeHookClockid_);
264 #endif
265 #ifdef ENABLE_CPUDATA
266     cpuUsageParser_->Finish();
267     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_CPU, dataSourceTypeCpuClockid_);
268 #endif
269 #ifdef ENABLE_NETWORK
270     networkParser_->Finish();
271     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NETWORK,
272                                                                       dataSourceTypeNetworkClockid_);
273 #endif
274 #ifdef ENABLE_PROCESS
275     processParser_->Finish();
276     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_PROCESS,
277                                                                       dataSourceTypeProcessClockid_);
278 #endif
279 #ifdef ENABLE_DISKIO
280     diskIOParser_->Finish();
281     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_DISKIO,
282                                                                       dataSourceTypeDiskioClockid_);
283 #endif
284 #ifdef ENABLE_ARKTS
285     jsMemoryParser_->Finish();
286     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_JSMEMORY,
287                                                                       dataSourceTypeJSMemoryClockid_);
288 #endif
289 #ifdef ENABLE_EBPF
290     ebpfDataParser_->Finish(); // keep final upate perf and ebpf data time range
291 #endif
292 #ifdef ENABLE_HIPERF
293     perfDataParser_->Finish();
294 #endif
295 #ifdef ENABLE_MEMORY
296     pbreaderMemParser_->Finish();
297     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_MEM, dataSourceTypeMemClockid_);
298 #endif
299 }
300 
WaitForParserEnd()301 void PbreaderParser::WaitForParserEnd()
302 {
303     if (parseThreadStarted_ || filterThreadStarted_) {
304         toExit_ = true;
305         while (!exited_) {
306             usleep(sleepDur_ * sleepDur_);
307         }
308     }
309     hasGotHeader_ = false;
310     WaitForHPluginParserEnd();
311     WaitForOtherPluginParserEnd();
312 #if defined(ENABLE_HTRACE) && defined(ENABLE_NATIVE_HOOK) && defined(ENABLE_HIPERF)
313     ParseNapiAsync();
314 #endif
315     traceDataCache_->GetDataSourceClockIdData()->Finish();
316     dataSegArray_.reset();
317     processedDataLen_ = 0;
318 }
319 
ParseTraceDataItem(const std::string & buffer)320 void PbreaderParser::ParseTraceDataItem(const std::string &buffer)
321 {
322     int32_t head = rawDataHead_;
323     if (!traceDataCache_->supportThread_ || traceDataCache_->isSplitFile_) {
324         dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
325         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
326         ParserData(dataSegArray_[head], traceDataCache_->isSplitFile_);
327         return;
328     }
329     while (!toExit_) {
330         if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) {
331             usleep(sleepDur_);
332             continue;
333         }
334         dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
335         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
336         rawDataHead_ = (rawDataHead_ + 1) % maxSegArraySize;
337         break;
338     }
339     if (!parseThreadStarted_) {
340         parseThreadStarted_ = true;
341         int32_t tmp = traceDataCache_->parserThreadNum_;
342         while (tmp--) {
343             parserThreadCount_++;
344             std::thread ParseTypeThread(&PbreaderParser::ParseThread, this);
345             ParseTypeThread.detach();
346             TS_LOGI("parser Thread:%d/%d start working ...\n", traceDataCache_->parserThreadNum_ - tmp,
347                     traceDataCache_->parserThreadNum_);
348         }
349     }
350     if (!filterThreadStarted_) {
351         filterThreadStarted_ = true;
352         std::thread FilterTypeThread(&PbreaderParser::FilterThread, this);
353         TS_LOGI("FilterThread start working ...");
354         FilterTypeThread.detach();
355     }
356 }
357 
358 #ifdef ENABLE_ARKTS
EnableFileSeparate(bool enabled)359 void PbreaderParser::EnableFileSeparate(bool enabled)
360 {
361     jsMemoryParser_->EnableSaveFile(enabled);
362 }
363 #endif
FilterData(PbreaderDataSegment & seg,bool isSplitFile)364 void PbreaderParser::FilterData(PbreaderDataSegment &seg, bool isSplitFile)
365 {
366     bool haveSplitSeg = false;
367     if (seg.dataType == DATA_SOURCE_TYPE_TRACE) {
368 #ifdef ENABLE_HTRACE
369         htraceCpuDetailParser_->FilterAllEventsReader();
370 #endif
371     }
372 #ifdef ENABLE_FFRT
373     else if (seg.dataType == DATA_SOURCE_TYPE_FFRT) {
374         pbreaderFfrtParser_->FilterAllEventsReader();
375     }
376 #endif
377 #ifdef ENABLE_NATIVE_HOOK
378     else if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK) {
379         pbreaderNativeHookParser_->Parse(seg, haveSplitSeg);
380     } else if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG) {
381         pbreaderNativeHookParser_->ParseConfigInfo(seg);
382     }
383 #endif
384 #ifdef ENABLE_MEMORY
385     else if (seg.dataType == DATA_SOURCE_TYPE_MEM) {
386         pbreaderMemParser_->Parse(seg, seg.timeStamp, seg.clockId);
387     } else if (seg.dataType == DATA_SOURCE_TYPE_MEM_CONFIG) {
388         pbreaderMemParser_->ParseMemoryConfig(seg);
389     }
390 #endif
391 #ifdef ENABLE_HILOG
392     else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) {
393         pbreaderHiLogParser_->Parse(seg.protoData, haveSplitSeg);
394     }
395 #endif
396 #ifdef ENABLE_CPUDATA
397     else if (seg.dataType == DATA_SOURCE_TYPE_CPU) {
398         cpuUsageParser_->Parse(seg.protoData, seg.timeStamp);
399     }
400 #endif
401 #ifdef ENABLE_HTDUMP
402     else if (seg.dataType == DATA_SOURCE_TYPE_FPS) {
403         pbreaderHidumpParser_->Parse(seg.protoData);
404         dataSourceTypeFpsClockid_ = pbreaderHidumpParser_->ClockId();
405     }
406 #endif
407 #ifdef ENABLE_NETWORK
408     else if (seg.dataType == DATA_SOURCE_TYPE_NETWORK) {
409         networkParser_->Parse(seg.protoData, seg.timeStamp);
410     }
411 #endif
412 #ifdef ENABLE_PROCESS
413     else if (seg.dataType == DATA_SOURCE_TYPE_PROCESS) {
414         processParser_->Parse(seg.protoData, seg.timeStamp);
415     }
416 #endif
417 #ifdef ENABLE_DISKIO
418     else if (seg.dataType == DATA_SOURCE_TYPE_DISKIO) {
419         diskIOParser_->Parse(seg.protoData, seg.timeStamp);
420     }
421 #endif
422 #ifdef ENABLE_ARKTS
423     else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY) {
424         jsMemoryParser_->Parse(seg.protoData, seg.timeStamp, traceDataCache_->SplitFileMinTime(),
425                                traceDataCache_->SplitFileMaxTime(), profilerPluginData_);
426     } else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY_CONFIG) {
427         jsMemoryParser_->ParseJSMemoryConfig(seg.protoData);
428     }
429 #endif
430 #ifdef ENABLE_HISYSEVENT
431     else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT) {
432         ProtoReader::HisyseventInfo_Reader hisyseventInfo(seg.protoData.data_, seg.protoData.size_);
433         hisyseventParser_->Parse(&hisyseventInfo, seg.timeStamp, haveSplitSeg);
434     } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT_CONFIG) {
435         ProtoReader::HisyseventConfig_Reader hisyseventConfig(seg.protoData.data_, seg.protoData.size_);
436         hisyseventParser_->Parse(&hisyseventConfig, seg.timeStamp);
437     }
438 #endif
439 #ifdef ENABLE_XPOWER
440     else if (seg.dataType == DATA_SOURCE_TYPE_XPOWER) {
441         xpowerParser_->Parse(seg, seg.timeStamp, seg.clockId);
442     }
443 #endif
444 #ifdef ENABLE_STREAM_EXTEND
445     else if (seg.dataType == DATA_SOURCE_TYPE_STREAM) {
446         pbreaderStreamParser_->Parse(seg);
447     }
448 #endif
449     if (traceDataCache_->isSplitFile_ && haveSplitSeg) {
450         mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
451     }
452     if (traceDataCache_->supportThread_ && !traceDataCache_->isSplitFile_) {
453         filterHead_ = (filterHead_ + 1) % maxSegArraySize;
454     }
455     seg.status = TS_PARSE_STATUS_INIT;
456 }
FilterThread()457 void PbreaderParser::FilterThread()
458 {
459     TS_LOGI("filter thread start work!");
460     while (true) {
461         PbreaderDataSegment &seg = dataSegArray_[filterHead_];
462         if (seg.status.load() == TS_PARSE_STATUS_INVALID) {
463             seg.status = TS_PARSE_STATUS_INIT;
464             filterHead_ = (filterHead_ + 1) % maxSegArraySize;
465             TS_LOGD("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_);
466             continue;
467         }
468         if (seg.status.load() != TS_PARSE_STATUS_PARSED) {
469             if (toExit_ && !parserThreadCount_) {
470                 TS_LOGI("exiting Filter Thread");
471                 exited_ = true;
472                 filterThreadStarted_ = false;
473                 TS_LOGI("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
474                         filterHead_, seg.status.load());
475                 return;
476             }
477             TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
478                     filterHead_, seg.status.load());
479             usleep(sleepDur_);
480             continue;
481         }
482         FilterData(seg, false);
483     }
484 }
485 
SpliteConfigData(const std::string & pluginName,const PbreaderDataSegment & dataSeg)486 bool PbreaderParser::SpliteConfigData(const std::string &pluginName, const PbreaderDataSegment &dataSeg)
487 {
488     if (EndWith(pluginName, "arkts-plugin_config")) {
489         std::string dataString(dataSeg.seg->c_str(), dataSeg.seg->length());
490         arkTsConfigData_ = lenBuffer_ + dataString;
491         return true;
492     } else if (EndWith(pluginName, "config")) {
493         mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
494         return true;
495     }
496     return false;
497 }
498 
SpliteDataBySegment(DataIndex pluginNameIndex,PbreaderDataSegment & dataSeg)499 bool PbreaderParser::SpliteDataBySegment(DataIndex pluginNameIndex, PbreaderDataSegment &dataSeg)
500 {
501     bool isOtherPlugin = false;
502 #ifdef ENABLE_HTRACE
503     isOtherPlugin = isOtherPlugin || ftracePluginIndex_.count(pluginNameIndex);
504 #endif
505 #ifdef ENABLE_FFRT
506     isOtherPlugin = isOtherPlugin || (ffrtPluginIndex_ == pluginNameIndex);
507 #endif
508 #ifdef ENABLE_HISYSEVENT
509     isOtherPlugin = isOtherPlugin || (hisyseventPluginIndex_ == pluginNameIndex);
510 #endif
511 #ifdef ENABLE_NATIVE_HOOK
512     isOtherPlugin = isOtherPlugin || nativeHookPluginIndex_.count(pluginNameIndex);
513 #endif
514 #ifdef ENABLE_HILOG
515     isOtherPlugin = isOtherPlugin || hilogPluginIndex_.count(pluginNameIndex);
516 #endif
517     if (isOtherPlugin) {
518         return false;
519     }
520     // need convert to Primary Time Plugin
521 #ifdef ENABLE_MEMORY
522     if (pluginNameIndex == memPluginIndex_) {
523         dataSeg.timeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, dataSeg.timeStamp);
524         UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, dataSeg.timeStamp, dataSeg.timeStamp);
525     }
526 #endif
527     if (dataSeg.timeStamp >= traceDataCache_->SplitFileMinTime() &&
528         dataSeg.timeStamp <= traceDataCache_->SplitFileMaxTime()) {
529         mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
530     }
531     if (pluginNameIndex == arktsPluginConfigIndex_ || pluginNameIndex == arktsPluginIndex_) {
532         return false;
533     }
534     return true;
535 }
ParseDataByPluginName(PbreaderDataSegment & dataSeg,DataIndex pulginNameIndex,const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,bool isSplitFile)536 void PbreaderParser::ParseDataByPluginName(PbreaderDataSegment &dataSeg,
537                                            DataIndex pulginNameIndex,
538                                            const ProtoReader::ProfilerPluginData_Reader &pluginDataZero,
539                                            bool isSplitFile)
540 {
541     if (ftracePluginIndex_.count(pulginNameIndex)) { // ok
542 #ifdef ENABLE_HTRACE
543         ParseFtrace(dataSeg);
544 #endif
545     }
546 #ifdef ENABLE_FFRT
547     else if (ffrtPluginIndex_ == pulginNameIndex) {
548         ParseFfrt(dataSeg);
549     } else if (ffrtPluginConfigIndex_ == pulginNameIndex) {
550         ParseFfrtConfig(dataSeg);
551     }
552 #endif
553 #ifdef ENABLE_NATIVE_HOOK
554     else if (nativeHookPluginIndex_.count(pulginNameIndex)) {
555         ParseNativeHook(dataSeg, isSplitFile);
556     } else if (pulginNameIndex == nativeHookConfigIndex_) {
557         ParseNativeHookConfig(dataSeg);
558     }
559 #endif
560 #ifdef ENABLE_MEMORY
561     else if (pulginNameIndex == memPluginIndex_) {
562         ParseMemory(pluginDataZero, dataSeg);
563     } else if (pulginNameIndex == memoryPluginConfigIndex_) {
564         ParseMemoryConfig(dataSeg, pluginDataZero);
565     }
566 #endif
567 #ifdef ENABLE_HILOG
568     else if (hilogPluginIndex_.count(pulginNameIndex)) {
569         ParseHilog(dataSeg);
570     }
571 #endif
572 #ifdef ENABLE_HTDUMP
573     else if (hidumpPluginIndex_.count(pulginNameIndex)) {
574         ParseFPS(dataSeg);
575     }
576 #endif
577 #ifdef ENABLE_CPUDATA
578     else if (pulginNameIndex == cpuPluginIndex_) {
579         ParseCpuUsage(dataSeg);
580     }
581 #endif
582 #ifdef ENABLE_NETWORK
583     else if (pulginNameIndex == networkPluginIndex_) {
584         ParseNetwork(dataSeg);
585     }
586 #endif
587 #ifdef ENABLE_DISKIO
588     else if (pulginNameIndex == diskioPluginIndex_) {
589         ParseDiskIO(dataSeg);
590     }
591 #endif
592 #ifdef ENABLE_PROCESS
593     else if (pulginNameIndex == processPluginIndex_) {
594         ParseProcess(dataSeg);
595     }
596 #endif
597 #ifdef ENABLE_HISYSEVENT
598     else if (pulginNameIndex == hisyseventPluginIndex_) {
599         ParseHisysevent(dataSeg);
600     } else if (pulginNameIndex == hisyseventPluginConfigIndex_) {
601         ParseHisyseventConfig(dataSeg);
602     }
603 #endif
604 #ifdef ENABLE_ARKTS
605     else if (pulginNameIndex == arktsPluginIndex_) {
606         ParseJSMemory(pluginDataZero, dataSeg, isSplitFile);
607     } else if (pulginNameIndex == arktsPluginConfigIndex_) {
608         ParseJSMemoryConfig(dataSeg);
609     }
610 #endif
611 #ifdef ENABLE_XPOWER
612     else if (pulginNameIndex == xpowerPluginIndex_) {
613         ParseXpower(dataSeg);
614     }
615 #endif
616 #ifdef ENABLE_STREAM_EXTEND
617     else if (pulginNameIndex == streamPluginIndex_) { // for trace extend demo
618         ParseStream(dataSeg);
619     }
620 #endif
621 }
622 
ParserData(PbreaderDataSegment & dataSeg,bool isSplitFile)623 void PbreaderParser::ParserData(PbreaderDataSegment &dataSeg, bool isSplitFile)
624 {
625     ProtoReader::ProfilerPluginData_Reader pluginDataZero(reinterpret_cast<const uint8_t *>(dataSeg.seg->c_str()),
626                                                           dataSeg.seg->length());
627     if (!pluginDataZero.has_name()) {
628         return;
629     }
630     auto pluginName = pluginDataZero.name().ToStdString();
631     auto pluginNameIndex = traceDataCache_->GetDataIndex(pluginName);
632     if (isSplitFile && SpliteConfigData(pluginName, dataSeg)) {
633         return;
634     }
635     if (pluginDataZero.has_tv_sec() && pluginDataZero.has_tv_nsec()) {
636         dataSeg.timeStamp = pluginDataZero.tv_sec() * SEC_TO_NS + pluginDataZero.tv_nsec();
637     }
638 
639     if (isSplitFile && SpliteDataBySegment(pluginNameIndex, dataSeg)) {
640         return;
641     }
642     if (supportPluginNameIndex_.count(pluginNameIndex)) {
643         dataSeg.protoData = pluginDataZero.data();
644         ParseDataByPluginName(dataSeg, pluginNameIndex, pluginDataZero, isSplitFile);
645     } else {
646 #if IS_WASM
647         TraceStreamerPluginOutFilter(reinterpret_cast<const char *>(pluginDataZero.data().data_),
648                                      pluginDataZero.data().size_, pluginName);
649 #endif
650         dataSeg.status = TS_PARSE_STATUS_INVALID;
651         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
652         return;
653     }
654     if (!traceDataCache_->supportThread_ || traceDataCache_->isSplitFile_) {
655         FilterData(dataSeg, isSplitFile);
656     }
657 }
ParseThread()658 void PbreaderParser::ParseThread()
659 {
660     TS_LOGI("parser thread start work!\n");
661     while (true) {
662         int32_t head = GetNextSegment();
663         if (head < 0) {
664             if (head == ERROR_CODE_EXIT) {
665                 TS_LOGI("parse thread exit");
666                 return;
667             } else if (head == ERROR_CODE_NODATA) {
668                 continue;
669             }
670         }
671         PbreaderDataSegment &dataSeg = dataSegArray_[head];
672         ParserData(dataSeg, false);
673     }
674 }
675 
676 #ifdef ENABLE_MEMORY
ParseMemory(const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,PbreaderDataSegment & dataSeg)677 void PbreaderParser::ParseMemory(const ProtoReader::ProfilerPluginData_Reader &pluginDataZero,
678                                  PbreaderDataSegment &dataSeg)
679 {
680     BuiltinClocks clockId = TS_CLOCK_REALTIME;
681     dataSourceTypeMemClockid_ = clockId;
682     dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
683     dataSeg.clockId = clockId;
684     dataSeg.status = TS_PARSE_STATUS_PARSED;
685 }
ParseMemoryConfig(PbreaderDataSegment & dataSeg,const ProtoReader::ProfilerPluginData_Reader & pluginDataZero)686 void PbreaderParser::ParseMemoryConfig(PbreaderDataSegment &dataSeg,
687                                        const ProtoReader::ProfilerPluginData_Reader &pluginDataZero)
688 {
689     if (pluginDataZero.has_sample_interval()) {
690         uint32_t sampleInterval = pluginDataZero.sample_interval();
691         traceDataCache_->GetTraceConfigData()->AppendNewData("memory_config", "sample_interval",
692                                                              std::to_string(sampleInterval));
693     }
694     dataSeg.dataType = DATA_SOURCE_TYPE_MEM_CONFIG;
695     dataSeg.status = TS_PARSE_STATUS_PARSED;
696 }
697 #endif
698 #ifdef ENABLE_HILOG
ParseHilog(PbreaderDataSegment & dataSeg)699 void PbreaderParser::ParseHilog(PbreaderDataSegment &dataSeg)
700 {
701     dataSeg.dataType = DATA_SOURCE_TYPE_HILOG;
702     dataSourceTypeHilogClockid_ = TS_CLOCK_REALTIME;
703     dataSeg.status = TS_PARSE_STATUS_PARSED;
704 }
705 #endif
706 #ifdef ENABLE_NATIVE_HOOK
ParseNativeHookConfig(PbreaderDataSegment & dataSeg)707 void PbreaderParser::ParseNativeHookConfig(PbreaderDataSegment &dataSeg)
708 {
709     dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG;
710     dataSeg.status = TS_PARSE_STATUS_PARSED;
711 }
ParseNativeHook(PbreaderDataSegment & dataSeg,bool isSplitFile)712 void PbreaderParser::ParseNativeHook(PbreaderDataSegment &dataSeg, bool isSplitFile)
713 {
714     dataSourceTypeNativeHookClockid_ = TS_CLOCK_REALTIME;
715     dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK;
716     dataSeg.status = TS_PARSE_STATUS_PARSED;
717     if (isSplitFile) {
718         dataSourceType_ = DATA_SOURCE_TYPE_NATIVEHOOK;
719     }
720 }
721 #endif
722 
723 #ifdef ENABLE_HTRACE
ParseFtrace(PbreaderDataSegment & dataSeg)724 void PbreaderParser::ParseFtrace(PbreaderDataSegment &dataSeg)
725 {
726     dataSeg.dataType = DATA_SOURCE_TYPE_TRACE;
727     ProtoReader::TracePluginResult_Reader tracePluginResult(dataSeg.protoData);
728     if (tracePluginResult.has_ftrace_cpu_stats()) {
729         auto cpuStats = *tracePluginResult.ftrace_cpu_stats();
730         ProtoReader::FtraceCpuStatsMsg_Reader ftraceCpuStatsMsg(cpuStats.data_, cpuStats.size_);
731         auto s = *ftraceCpuStatsMsg.per_cpu_stats();
732         ProtoReader::PerCpuStatsMsg_Reader perCpuStatsMsg(s.data_, s.size_);
733         TS_LOGD("s.overrun():%" PRIu64 "", perCpuStatsMsg.overrun());
734         TS_LOGD("s.dropped_events():%" PRIu64 "", perCpuStatsMsg.dropped_events());
735         auto clock = ftraceCpuStatsMsg.trace_clock().ToStdString();
736         if (clock == "boot") {
737             clock_ = TS_CLOCK_BOOTTIME;
738         } else if (clock == "mono") {
739             clock_ = TS_MONOTONIC;
740         } else {
741             TS_LOGI("invalid clock:%s", clock.c_str());
742             dataSeg.status = TS_PARSE_STATUS_INVALID;
743             return;
744         }
745         dataSeg.clockId = clock_;
746         dataSourceTypeTraceClockid_ = clock_;
747         dataSeg.status = TS_PARSE_STATUS_PARSED;
748         return;
749     }
750     bool haveSplitSeg = false;
751     dataSeg.clockId = clock_;
752     if (tracePluginResult.has_ftrace_cpu_detail()) {
753         htraceCpuDetailParser_->Parse(dataSeg, tracePluginResult, haveSplitSeg);
754     }
755     if (tracePluginResult.has_symbols_detail()) {
756         htraceSymbolsDetailParser_->Parse(dataSeg.protoData); // has Event
757         haveSplitSeg = true;
758     }
759     if (tracePluginResult.has_clocks_detail()) {
760         pbreaderClockDetailParser_->Parse(dataSeg.protoData); // has Event
761         haveSplitSeg = true;
762     }
763     if (traceDataCache_->isSplitFile_ && haveSplitSeg) {
764         mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
765     }
766     if (tracePluginResult.has_ftrace_cpu_detail() || tracePluginResult.has_clocks_detail() ||
767         tracePluginResult.has_symbols_detail()) {
768         dataSeg.status = TS_PARSE_STATUS_PARSED;
769     } else {
770         dataSeg.status = TS_PARSE_STATUS_INVALID;
771     }
772 }
773 #endif
774 #ifdef ENABLE_FFRT
ParseFfrtConfig(PbreaderDataSegment & dataSeg)775 void PbreaderParser::ParseFfrtConfig(PbreaderDataSegment &dataSeg)
776 {
777     pbreaderFfrtParser_->SetFfrtSrcClockid(dataSeg);
778     dataSeg.dataType = DATA_SOURCE_TYPE_FFRT_CONFIG;
779     dataSeg.status = TS_PARSE_STATUS_PARSED;
780 }
ParseFfrt(PbreaderDataSegment & dataSeg)781 void PbreaderParser::ParseFfrt(PbreaderDataSegment &dataSeg)
782 {
783     bool haveSplitSeg = false;
784     pbreaderFfrtParser_->Parser(dataSeg, haveSplitSeg);
785     if (haveSplitSeg) {
786         mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
787     }
788     dataSeg.dataType = DATA_SOURCE_TYPE_FFRT;
789     dataSeg.status = TS_PARSE_STATUS_PARSED;
790 }
791 #endif
792 #ifdef ENABLE_HTDUMP
ParseFPS(PbreaderDataSegment & dataSeg)793 void PbreaderParser::ParseFPS(PbreaderDataSegment &dataSeg)
794 {
795     dataSeg.dataType = DATA_SOURCE_TYPE_FPS;
796     dataSeg.status = TS_PARSE_STATUS_PARSED;
797 }
798 #endif
799 
800 #ifdef ENABLE_CPUDATA
ParseCpuUsage(PbreaderDataSegment & dataSeg)801 void PbreaderParser::ParseCpuUsage(PbreaderDataSegment &dataSeg)
802 {
803     dataSourceTypeCpuClockid_ = TS_CLOCK_REALTIME;
804     dataSeg.dataType = DATA_SOURCE_TYPE_CPU;
805     dataSeg.status = TS_PARSE_STATUS_PARSED;
806 }
807 #endif
808 #ifdef ENABLE_NETWORK
ParseNetwork(PbreaderDataSegment & dataSeg)809 void PbreaderParser::ParseNetwork(PbreaderDataSegment &dataSeg)
810 {
811     dataSourceTypeNetworkClockid_ = TS_CLOCK_REALTIME;
812     dataSeg.dataType = DATA_SOURCE_TYPE_NETWORK;
813     dataSeg.status = TS_PARSE_STATUS_PARSED;
814 }
815 #endif
816 #ifdef ENABLE_XPOWER
ParseXpower(PbreaderDataSegment & dataSeg)817 void PbreaderParser::ParseXpower(PbreaderDataSegment &dataSeg)
818 {
819     dataSeg.dataType = DATA_SOURCE_TYPE_XPOWER;
820     dataSeg.status = TS_PARSE_STATUS_PARSED;
821 }
822 #endif
823 #ifdef ENABLE_DISKIO
ParseDiskIO(PbreaderDataSegment & dataSeg)824 void PbreaderParser::ParseDiskIO(PbreaderDataSegment &dataSeg)
825 {
826     dataSourceTypeDiskioClockid_ = TS_CLOCK_REALTIME;
827     dataSeg.dataType = DATA_SOURCE_TYPE_DISKIO;
828     dataSeg.status = TS_PARSE_STATUS_PARSED;
829 }
830 #endif
831 
832 #ifdef ENABLE_PROCESS
ParseProcess(PbreaderDataSegment & dataSeg)833 void PbreaderParser::ParseProcess(PbreaderDataSegment &dataSeg)
834 {
835     dataSourceTypeProcessClockid_ = TS_CLOCK_BOOTTIME;
836     dataSeg.dataType = DATA_SOURCE_TYPE_PROCESS;
837     dataSeg.status = TS_PARSE_STATUS_PARSED;
838 }
839 #endif
840 
841 #ifdef ENABLE_HISYSEVENT
ParseHisysevent(PbreaderDataSegment & dataSeg)842 void PbreaderParser::ParseHisysevent(PbreaderDataSegment &dataSeg)
843 {
844     dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
845     dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT;
846     dataSeg.status = TS_PARSE_STATUS_PARSED;
847 }
ParseHisyseventConfig(PbreaderDataSegment & dataSeg)848 void PbreaderParser::ParseHisyseventConfig(PbreaderDataSegment &dataSeg)
849 {
850     dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
851     dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT_CONFIG;
852     dataSeg.status = TS_PARSE_STATUS_PARSED;
853 }
854 #endif
855 
856 #ifdef ENABLE_ARKTS
ParseJSMemory(const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,PbreaderDataSegment & dataSeg,bool isSplitFile)857 void PbreaderParser::ParseJSMemory(const ProtoReader::ProfilerPluginData_Reader &pluginDataZero,
858                                    PbreaderDataSegment &dataSeg,
859                                    bool isSplitFile)
860 {
861     if (isSplitFile) {
862         dataSourceType_ = DATA_SOURCE_TYPE_JSMEMORY;
863         profilerPluginData_.name = pluginDataZero.name().ToStdString();
864         profilerPluginData_.status = pluginDataZero.status();
865         profilerPluginData_.clockId = pluginDataZero.clock_id();
866         profilerPluginData_.tvSec = pluginDataZero.tv_sec();
867         profilerPluginData_.tvNsec = pluginDataZero.tv_nsec();
868         profilerPluginData_.version = pluginDataZero.version().ToStdString();
869         profilerPluginData_.sampleInterval = pluginDataZero.sample_interval();
870     }
871     dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
872     dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY;
873     dataSeg.status = TS_PARSE_STATUS_PARSED;
874 }
ParseJSMemoryConfig(PbreaderDataSegment & dataSeg)875 void PbreaderParser::ParseJSMemoryConfig(PbreaderDataSegment &dataSeg)
876 {
877     dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
878     dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY_CONFIG;
879     dataSeg.status = TS_PARSE_STATUS_PARSED;
880 }
881 #endif
882 
883 #ifdef ENABLE_STREAM_EXTEND
ParseStream(PbreaderDataSegment & dataSeg)884 void PbreaderParser::ParseStream(PbreaderDataSegment &dataSeg)
885 {
886     dataSeg.dataType = DATA_SOURCE_TYPE_STREAM;
887     dataSeg.status = TS_PARSE_STATUS_PARSED;
888 }
889 #endif
890 
GetNextSegment()891 int32_t PbreaderParser::GetNextSegment()
892 {
893     int32_t head;
894     std::lock_guard<std::mutex> muxLockGuard(pbreaderDataSegMux_);
895     head = parseHead_;
896     PbreaderDataSegment &pbreaderDataSegmentSeg = dataSegArray_[head];
897     if (pbreaderDataSegmentSeg.status.load() != TS_PARSE_STATUS_SEPRATED) {
898         if (toExit_) {
899             parserThreadCount_--;
900             TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_);
901             TS_LOGI("seprateHead_x:\t%d, parseHead_:\t%d, filterHead_:\t%d status:%d\n", rawDataHead_, parseHead_,
902                     filterHead_, pbreaderDataSegmentSeg.status.load());
903             if (!parserThreadCount_ && !filterThreadStarted_) {
904                 exited_ = true;
905             }
906             return ERROR_CODE_EXIT;
907         }
908         usleep(sleepDur_);
909         return ERROR_CODE_NODATA;
910     }
911     parseHead_ = (parseHead_ + 1) % maxSegArraySize;
912     pbreaderDataSegmentSeg.status = TS_PARSE_STATUS_PARSING;
913     return head;
914 }
915 #ifdef ENABLE_EBPF
CalcEbpfCutOffset(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)916 bool PbreaderParser::CalcEbpfCutOffset(std::deque<uint8_t>::iterator &packagesBegin, size_t &currentLength)
917 {
918     auto standaloneDataLength = profilerDataLength_ - packetHeaderLength_;
919     if (traceDataCache_->isSplitFile_ && !parsedEbpfOver_) {
920         if (!hasInitEbpfPublicData_) {
921             // Record the offset of Hiperf's 1024-byte header relative to the entire file.
922             ebpfDataParser_->SetEbpfDataOffset(processedDataLen_);
923             ebpfDataParser_->SetSpliteTimeRange(traceDataCache_->SplitFileMinTime(),
924                                                 traceDataCache_->SplitFileMaxTime());
925             parsedFileOffset_ += profilerDataLength_ - packetHeaderLength_;
926             hasInitEbpfPublicData_ = true;
927         }
928         parsedEbpfOver_ = ebpfDataParser_->AddAndSplitEbpfData(packagesBuffer_);
929         if (parsedEbpfOver_) {
930             profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
931             hasGotHeader_ = false;
932             processedDataLen_ += standaloneDataLength;
933         }
934         return false;
935     }
936     if (!traceDataCache_->isSplitFile_ && packagesBuffer_.size() >= standaloneDataLength) {
937         ebpfDataParser_->InitAndParseEbpfData(packagesBuffer_, standaloneDataLength);
938         currentLength -= standaloneDataLength;
939         packagesBegin += standaloneDataLength;
940         profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
941         hasGotHeader_ = false;
942         return true;
943     }
944     return false;
945 }
946 #endif
947 
GetHeaderAndUpdateLengthMark(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)948 bool PbreaderParser::GetHeaderAndUpdateLengthMark(std::deque<uint8_t>::iterator &packagesBegin, size_t &currentLength)
949 {
950     if (!hasGotHeader_) {
951         if (!InitProfilerTraceFileHeader()) {
952             return false;
953         }
954         packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + packetHeaderLength_);
955         processedDataLen_ += packetHeaderLength_;
956         currentLength -= packetHeaderLength_;
957         packagesBegin += packetHeaderLength_;
958         parsedFileOffset_ += packetHeaderLength_;
959         pbreaderCurentLength_ = profilerDataLength_ - packetHeaderLength_;
960         hasGotHeader_ = true;
961         if (!currentLength) {
962             return false;
963         }
964     }
965     return true;
966 }
967 #if IS_WASM
ParseSDKData()968 bool PbreaderParser::ParseSDKData()
969 {
970     if (packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_) {
971         auto thirdPartySize = profilerDataLength_ - packetHeaderLength_;
972         auto buffer = std::make_unique<uint8_t[]>(thirdPartySize).get();
973         std::copy(packagesBuffer_.begin(), packagesBuffer_.begin() + thirdPartySize, buffer);
974         TraceStreamerPluginOutFilter(reinterpret_cast<const char *>(buffer), thirdPartySize, standalonePluginName_);
975         return true;
976     }
977     return false;
978 }
979 #endif
980 
ParseSegLengthAndEnsureSegDataEnough(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)981 bool PbreaderParser::ParseSegLengthAndEnsureSegDataEnough(std::deque<uint8_t>::iterator &packagesBegin,
982                                                           size_t &currentLength)
983 {
984     std::string bufferLine;
985     if (!hasGotSegLength_) {
986         if (currentLength < packetSegLength_) {
987             return false;
988         }
989         bufferLine.assign(packagesBegin, packagesBegin + packetSegLength_);
990         const uint32_t *len = reinterpret_cast<const uint32_t *>(bufferLine.data());
991         nextLength_ = *len;
992         lenBuffer_ = bufferLine;
993         pbreaderLength_ += nextLength_ + packetSegLength_;
994         hasGotSegLength_ = true;
995         currentLength -= packetSegLength_;
996         packagesBegin += packetSegLength_;
997         parsedFileOffset_ += packetSegLength_;
998         splitFileOffset_ = profilerDataLength_ - pbreaderCurentLength_;
999         pbreaderCurentLength_ -= packetSegLength_;
1000     }
1001     if (currentLength < nextLength_) {
1002         return false;
1003     }
1004     return true;
1005 }
ParseDataRecursively(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)1006 bool PbreaderParser::ParseDataRecursively(std::deque<uint8_t>::iterator &packagesBegin, size_t &currentLength)
1007 {
1008     TS_CHECK_TRUE_RET(GetHeaderAndUpdateLengthMark(packagesBegin, currentLength), false);
1009 #ifdef ENABLE_HIPERF
1010     if (profilerDataType_ == ProfilerTraceFileHeader::HIPERF_DATA) {
1011         return ParseHiperfData(packagesBegin, currentLength);
1012     }
1013 #endif
1014     if (profilerDataType_ == ProfilerTraceFileHeader::STANDALONE_DATA) {
1015         if (EBPF_PLUGIN_NAME.compare(standalonePluginName_) == 0) {
1016 #ifdef ENABLE_EBPF
1017             return CalcEbpfCutOffset(packagesBegin, currentLength);
1018 #else
1019             return false;
1020 #endif
1021         } else {
1022 #if IS_WASM
1023             TS_CHECK_TRUE_RET(ParseSDKData(), false); // 三方sdk逻辑待验证。
1024 #endif
1025         }
1026     }
1027     std::string bufferLine;
1028     while (true) {
1029         TS_CHECK_TRUE_RET(ParseSegLengthAndEnsureSegDataEnough(packagesBegin, currentLength), true);
1030         bufferLine.assign(packagesBegin, packagesBegin + nextLength_);
1031         ParseTraceDataItem(bufferLine);
1032         hasGotSegLength_ = false;
1033         packagesBegin += nextLength_;
1034         currentLength -= nextLength_;
1035         parsedFileOffset_ += nextLength_;
1036         if (nextLength_ > pbreaderCurentLength_) {
1037             TS_LOGE("fatal error, data length not match nextLength_:%u, pbreaderCurentLength_:%" PRIu64 "", nextLength_,
1038                     pbreaderCurentLength_);
1039         }
1040         pbreaderCurentLength_ -= nextLength_;
1041         if (pbreaderCurentLength_ == 0) {
1042             hasGotHeader_ = false;
1043             processedDataLen_ += packagesBegin - packagesBuffer_.begin();
1044             packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
1045             profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
1046             TS_LOGD("read proto finished!");
1047             return ParseDataRecursively(packagesBegin, currentLength);
1048         }
1049     }
1050     return true;
1051 }
1052 
ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size,bool isFinish)1053 void PbreaderParser::ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, bool isFinish)
1054 {
1055     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
1056     auto packagesBegin = packagesBuffer_.begin();
1057     auto currentLength = packagesBuffer_.size();
1058     if (ParseDataRecursively(packagesBegin, currentLength)) {
1059         processedDataLen_ += packagesBegin - packagesBuffer_.begin();
1060         packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
1061     }
1062     return;
1063 }
1064 #ifdef ENABLE_HIPERF
ParseHiperfData(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)1065 bool PbreaderParser::ParseHiperfData(std::deque<uint8_t>::iterator &packagesBegin, size_t &currentLength)
1066 {
1067     if (!traceDataCache_->isSplitFile_) {
1068         if (packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_) {
1069             auto size = profilerDataLength_ - packetHeaderLength_;
1070             (void)perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size, processedDataLen_, false, true);
1071             currentLength -= size;
1072             packagesBegin += size;
1073             profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
1074             hasGotHeader_ = false;
1075             return true;
1076         }
1077         return false;
1078     }
1079     bool isFinish = perfProcessedLen_ + packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_;
1080     auto size = packagesBuffer_.size();
1081     if (isFinish) {
1082         size = profilerDataLength_ - packetHeaderLength_ - perfProcessedLen_;
1083     }
1084     auto ret = perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size, processedDataLen_, true, isFinish);
1085     perfProcessedLen_ += ret;
1086     currentLength -= ret;
1087     packagesBegin += ret;
1088     if (isFinish) {
1089         profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
1090         hasGotHeader_ = false;
1091     }
1092     return true;
1093 }
StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size,int32_t isFinish)1094 void PbreaderParser::StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, int32_t isFinish)
1095 {
1096     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
1097     if (!traceDataCache_->isSplitFile_) {
1098         return;
1099     }
1100 
1101     uint64_t length = packagesBuffer_.size();
1102     auto ret = perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, length, 0, true, isFinish);
1103     perfProcessedLen_ += ret;
1104     processedDataLen_ += ret;
1105     packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + ret);
1106     return;
1107 }
TraceDataSegmentEnd(bool isSplitFile)1108 void PbreaderParser::TraceDataSegmentEnd(bool isSplitFile)
1109 {
1110     perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, packagesBuffer_.size(), 0, isSplitFile, true);
1111     packagesBuffer_.clear();
1112     return;
1113 }
1114 #endif
1115 
InitProfilerTraceFileHeader()1116 bool PbreaderParser::InitProfilerTraceFileHeader()
1117 {
1118     if (packagesBuffer_.size() < packetHeaderLength_) {
1119         TS_LOGI("buffer size less than profiler trace file header");
1120         return false;
1121     }
1122     uint8_t buffer[packetHeaderLength_];
1123     (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
1124     int32_t i = 0;
1125     for (auto it = packagesBuffer_.begin(); it != packagesBuffer_.begin() + packetHeaderLength_; ++it, ++i) {
1126         buffer[i] = *it;
1127     }
1128     ProfilerTraceFileHeader *pHeader = reinterpret_cast<ProfilerTraceFileHeader *>(buffer);
1129     if (pHeader->data.length <= packetHeaderLength_ || pHeader->data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
1130         TS_LOGE("Profiler Trace data is truncated or invalid magic! len = %" PRIu64 ", maigc = %" PRIx64 "",
1131                 pHeader->data.length, pHeader->data.magic);
1132         return false;
1133     }
1134     if (pHeader->data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) {
1135 #ifdef ENABLE_HIPERF
1136         perfDataParser_->RecordPerfProfilerHeader(buffer, packetHeaderLength_);
1137 #endif
1138     } else if (pHeader->data.dataType == ProfilerTraceFileHeader::STANDALONE_DATA &&
1139                EBPF_PLUGIN_NAME.compare(pHeader->data.standalonePluginName) == 0) {
1140 #ifdef ENABLE_EBPF
1141         ebpfDataParser_->RecordEbpfProfilerHeader(buffer, packetHeaderLength_);
1142 #endif
1143     } else {
1144         auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, packetHeaderLength_);
1145         if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
1146             TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %" PRIx64 "", ret,
1147                     profilerTraceFileHeader_.data.magic);
1148             return false;
1149         }
1150     }
1151     profilerDataLength_ = pHeader->data.length;
1152     profilerDataType_ = pHeader->data.dataType;
1153     memcpy_s(standalonePluginName_, sizeof(standalonePluginName_), pHeader->data.standalonePluginName,
1154              sizeof(standalonePluginName_));
1155 
1156     TS_LOGI("magic = %" PRIx64 ", length = %" PRIu64 ", dataType = %x, boottime = %" PRIu64 "", pHeader->data.magic,
1157             pHeader->data.length, pHeader->data.dataType, pHeader->data.boottime);
1158 #if IS_WASM
1159     const int32_t DATA_TYPE_CLOCK = 100;
1160     TraceStreamerPluginOutSendData(reinterpret_cast<char *>(buffer), packetHeaderLength_, DATA_TYPE_CLOCK);
1161 #endif
1162     pbreaderClockDetailParser_->Parse(pHeader);
1163     return true;
1164 }
1165 
1166 #if defined(ENABLE_HTRACE) && defined(ENABLE_NATIVE_HOOK) && defined(ENABLE_HIPERF)
ParseNapiAsync()1167 void PbreaderParser::ParseNapiAsync()
1168 {
1169     // 将native memory中存在的traceid取出, 并记录其对应的callstackid
1170     std::unordered_map<std::string, uint32_t> traceidToCallchainidMap;
1171     GetTraceidInfoFromNativeHook(traceidToCallchainidMap);
1172 
1173     // 从callstack表中获取所有的traceid, 根据其所属的itid将SliceInfo存入对应queue
1174     std::unordered_map<uint64_t, std::queue<SliceInfo>> itidToCallstackIdsMap;
1175     GetTraceidInfoFromCallstack(traceidToCallchainidMap, itidToCallstackIdsMap);
1176 
1177     // 筛选出包含NativeAsyncWork::AsyncWorkCallback的函数栈的callchainid, 将其存入callchainIdSet
1178     std::unordered_set<uint32_t> callchainIdSet;
1179     GetCallchainIdSetFromHiperf(callchainIdSet);
1180 
1181     DumpDataFromHiperf(traceidToCallchainidMap, callchainIdSet, itidToCallstackIdsMap);
1182 }
1183 
GetTraceidInfoFromNativeHook(std::unordered_map<std::string,uint32_t> & traceidToCallchainidMap)1184 void PbreaderParser::GetTraceidInfoFromNativeHook(std::unordered_map<std::string, uint32_t> &traceidToCallchainidMap)
1185 {
1186     auto nativeHook = traceDataCache_->GetConstNativeHookData();
1187     std::string preWord("napi:");
1188     for (int i = 0; i < nativeHook.Size(); i++) {
1189         auto subType = nativeHook.SubTypes()[i];
1190         if (subType == INVALID_UINT64) {
1191             continue;
1192         }
1193         auto subTypeStr = traceDataCache_->GetDataFromDict(subType);
1194         if (!StartWith(subTypeStr, preWord)) {
1195             continue;
1196         }
1197         auto pos = subTypeStr.find(preWord) + preWord.size();
1198         auto traceidStr = subTypeStr.substr(pos, subTypeStr.find_last_of(':') - pos);
1199         auto traceidIndex = traceDataCache_->GetDataIndex(traceidStr);
1200         traceidToCallchainidMap.emplace(std::move(traceidStr), nativeHook.CallChainIds()[i]);
1201     }
1202 }
1203 
GetTraceidInfoFromCallstack(const std::unordered_map<std::string,uint32_t> & traceidToCallchainidMap,std::unordered_map<uint64_t,std::queue<SliceInfo>> & itidToCallstackIdsMap)1204 void PbreaderParser::GetTraceidInfoFromCallstack(
1205     const std::unordered_map<std::string, uint32_t> &traceidToCallchainidMap,
1206     std::unordered_map<uint64_t, std::queue<SliceInfo>> &itidToCallstackIdsMap)
1207 {
1208     auto callStack = traceDataCache_->GetConstInternalSlicesData();
1209     std::string preWord("traceid:");
1210     std::string invalidTraceidStr("0x0");
1211     for (int i = 0; i < callStack.Size(); i++) {
1212         auto name = traceDataCache_->GetDataFromDict(callStack.NamesData()[i]);
1213         if (!StartWith(name, "H:Napi execute, name:") || callStack.DursData()[i] == INVALID_UINT64) {
1214             continue;
1215         }
1216         auto traceidStr = name.substr(name.find(preWord) + preWord.size());
1217         if (traceidStr == invalidTraceidStr) {
1218             continue;
1219         }
1220         if (traceidToCallchainidMap.find(traceidStr) == traceidToCallchainidMap.end()) {
1221             continue;
1222         }
1223         auto iter = itidToCallstackIdsMap.find(callStack.CallIds()[i]);
1224         if (iter == itidToCallstackIdsMap.end()) {
1225             itidToCallstackIdsMap.emplace(callStack.CallIds()[i], std::queue<SliceInfo>());
1226             iter = itidToCallstackIdsMap.find(callStack.CallIds()[i]);
1227         }
1228         iter->second.emplace(callStack.TimeStampData()[i], callStack.TimeStampData()[i] + callStack.DursData()[i],
1229                              traceidStr);
1230     }
1231 }
1232 
GetCallchainIdSetFromHiperf(std::unordered_set<uint32_t> & callchainIdSet)1233 void PbreaderParser::GetCallchainIdSetFromHiperf(std::unordered_set<uint32_t> &callchainIdSet)
1234 {
1235     auto perfCallChain = traceDataCache_->GetConstPerfCallChainData();
1236     std::string asyncWork("NativeAsyncWork::AsyncWorkCallback");
1237     for (int i = 0; i < perfCallChain.Size(); i++) {
1238         auto callchainId = perfCallChain.CallChainIds()[i];
1239         if (callchainIdSet.find(callchainId) != callchainIdSet.end()) {
1240             continue;
1241         }
1242         auto nameIndex = perfCallChain.Names()[i];
1243         if (nameIndex == INVALID_UINT64) {
1244             continue;
1245         }
1246         auto name = traceDataCache_->GetDataFromDict(nameIndex);
1247         if (name.find(asyncWork) != std::string::npos) {
1248             callchainIdSet.emplace(perfCallChain.CallChainIds()[i]);
1249         }
1250     }
1251 }
1252 
DumpDataFromHiperf(const std::unordered_map<std::string,uint32_t> & traceidToCallchainidMap,const std::unordered_set<uint32_t> & callchainIdSet,std::unordered_map<uint64_t,std::queue<SliceInfo>> & itidToCallstackIdsMap)1253 void PbreaderParser::DumpDataFromHiperf(const std::unordered_map<std::string, uint32_t> &traceidToCallchainidMap,
1254                                         const std::unordered_set<uint32_t> &callchainIdSet,
1255                                         std::unordered_map<uint64_t, std::queue<SliceInfo>> &itidToCallstackIdsMap)
1256 {
1257     auto perfThread = traceDataCache_->GetConstPerfThreadData();
1258     std::unordered_map<uint32_t, uint32_t> tidToPidMap;
1259     for (size_t i = 0; i < perfThread.Size(); i++) {
1260         tidToPidMap.emplace(perfThread.Tids()[i], perfThread.Pids()[i]);
1261     }
1262     auto perfSample = traceDataCache_->GetConstPerfSampleData();
1263     auto callStack = traceDataCache_->GetConstInternalSlicesData();
1264     for (size_t i = 0; i < perfSample.Size(); i++) {
1265         // callchainid未命中, 即当前栈不包含NativeAsyncWork::AsyncWorkCallback
1266         if (callchainIdSet.find(perfSample.SampleIds()[i]) == callchainIdSet.end()) {
1267             continue;
1268         }
1269         // 根据tid和tsPerfSample查询对应的SliceInfo
1270         auto itid = streamFilters_->processFilter_->GetInternalTid(perfSample.Tids()[i]);
1271         if (itidToCallstackIdsMap.find(itid) == itidToCallstackIdsMap.end()) {
1272             continue;
1273         }
1274         auto tsPerfSample = perfSample.TimestampTraces()[i];
1275         auto queue = itidToCallstackIdsMap.at(itid);
1276         while (!queue.empty() && queue.front().tsEnd_ < tsPerfSample) {
1277             queue.pop();
1278         }
1279         if (queue.empty() || tsPerfSample < queue.front().tsBegin_) {
1280             continue;
1281         }
1282         // 根据traceid查询native侧的callchainid
1283         auto iterNative = traceidToCallchainidMap.find(queue.front().traceid_);
1284         if (iterNative == traceidToCallchainidMap.end()) {
1285             continue;
1286         }
1287         // 根据tid查询pid
1288         auto iterPid = tidToPidMap.find(perfSample.Tids()[i]);
1289         if (iterPid == tidToPidMap.end()) {
1290             continue;
1291         }
1292         PerfNapiAsyncRow perfNapiAsyncRow{
1293             .timeStamp = tsPerfSample,
1294             .traceid = traceDataCache_->GetDataIndex(queue.front().traceid_),
1295             .cpuId = static_cast<uint8_t>(perfSample.CpuIds()[i]),
1296             .threadId = perfSample.Tids()[i],
1297             .processId = iterPid->second,
1298             .callerCallchainid = iterNative->second,
1299             .calleeCallchainid = perfSample.SampleIds()[i],
1300             .perfSampleId = i,
1301             .eventCount = perfSample.EventCounts()[i],
1302             .eventTypeId = perfSample.EventTypeIds()[i],
1303         };
1304         traceDataCache_->GetPerfNapiAsyncData()->AppendNewPerfNapiAsync(perfNapiAsyncRow);
1305     }
1306 }
1307 #endif
1308 } // namespace TraceStreamer
1309 } // namespace SysTuning
1310