• 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 "htrace_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 #include "ftrace_event.pbreader.h"
24 #include "log.h"
25 #include "memory_plugin_result.pbreader.h"
26 #include "stat_filter.h"
27 #include "trace_plugin_result.pbreader.h"
28 #if IS_WASM
29 #include "../rpc/wasm_func.h"
30 #endif
31 namespace SysTuning {
32 namespace TraceStreamer {
HtraceParser(TraceDataCache * dataCache,const TraceStreamerFilters * filters)33 HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters)
34     : ParserBase(filters),
35       traceDataCache_(dataCache),
36       htraceCpuDetailParser_(std::make_unique<HtraceCpuDetailParser>(dataCache, filters)),
37       htraceSymbolsDetailParser_(std::make_unique<HtraceSymbolsDetailParser>(dataCache, filters)),
38       htraceMemParser_(std::make_unique<HtraceMemParser>(dataCache, filters)),
39       htraceClockDetailParser_(std::make_unique<HtraceClockDetailParser>(dataCache, filters)),
40       htraceHiLogParser_(std::make_unique<HtraceHiLogParser>(dataCache, filters)),
41       htraceNativeHookParser_(std::make_unique<HtraceNativeHookParser>(dataCache, filters)),
42       htraceHidumpParser_(std::make_unique<HtraceHidumpParser>(dataCache, filters)),
43       cpuUsageParser_(std::make_unique<HtraceCpuDataParser>(dataCache, filters)),
44       networkParser_(std::make_unique<HtraceNetworkParser>(dataCache, filters)),
45       diskIOParser_(std::make_unique<HtraceDiskIOParser>(dataCache, filters)),
46       processParser_(std::make_unique<HtraceProcessParser>(dataCache, filters)),
47       hisyseventParser_(std::make_unique<HtraceHisyseventParser>(dataCache, filters)),
48       jsMemoryParser_(std::make_unique<HtraceJSMemoryParser>(dataCache, filters)),
49       perfDataParser_(std::make_unique<PerfDataParser>(dataCache, filters)),
50       ebpfDataParser_(std::make_unique<EbpfDataParser>(dataCache, filters))
51 {
52     InitPluginNameIndex();
53     if (traceDataCache_->supportThread_) {
54         dataSegArray_ = std::make_unique<HtraceDataSegment[]>(maxSegArraySize);
55     } else {
56         dataSegArray_ = std::make_unique<HtraceDataSegment[]>(1);
57     }
58 }
InitPluginNameIndex()59 void HtraceParser::InitPluginNameIndex()
60 {
61     nativeHookPluginIndex_.insert(traceDataCache_->GetDataIndex("nativehook"));
62     nativeHookPluginIndex_.insert(traceDataCache_->GetDataIndex("hookdaemon"));
63     nativeHookConfigIndex_ = traceDataCache_->GetDataIndex("nativehook_config");
64     hisyseventPluginIndex_ = traceDataCache_->GetDataIndex("hisysevent-plugin");
65     hisyseventPluginConfigIndex_ = traceDataCache_->GetDataIndex("hisysevent-plugin_config");
66     memPluginIndex_ = traceDataCache_->GetDataIndex("memory-plugin");
67     memoryPluginConfigIndex_ = traceDataCache_->GetDataIndex("memory-plugin_config");
68     ftracePluginIndex_.insert(traceDataCache_->GetDataIndex("ftrace-plugin"));
69     ftracePluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libftrace_plugin.z.so"));
70     hilogPluginIndex_.insert(traceDataCache_->GetDataIndex("hilog-plugin"));
71     hilogPluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libhilogplugin.z.so"));
72     hidumpPluginIndex_.insert(traceDataCache_->GetDataIndex("hidump-plugin"));
73     hidumpPluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libhidumpplugin.z.so"));
74     cpuPluginIndex_ = traceDataCache_->GetDataIndex("cpu-plugin");
75     networkPluginIndex_ = traceDataCache_->GetDataIndex("network-plugin");
76     diskioPluginIndex_ = traceDataCache_->GetDataIndex("diskio-plugin");
77     processPluginIndex_ = traceDataCache_->GetDataIndex("process-plugin");
78     arktsPluginIndex_ = traceDataCache_->GetDataIndex("arkts-plugin");
79     arktsPluginConfigIndex_ = traceDataCache_->GetDataIndex("arkts-plugin_config");
80     supportPluginNameIndex_.insert(nativeHookPluginIndex_.begin(), nativeHookPluginIndex_.end());
81     supportPluginNameIndex_.insert(nativeHookConfigIndex_);
82     supportPluginNameIndex_.insert(hisyseventPluginIndex_);
83     supportPluginNameIndex_.insert(hisyseventPluginConfigIndex_);
84     supportPluginNameIndex_.insert(memPluginIndex_);
85     supportPluginNameIndex_.insert(memoryPluginConfigIndex_);
86     supportPluginNameIndex_.insert(ftracePluginIndex_.begin(), ftracePluginIndex_.end());
87     supportPluginNameIndex_.insert(hilogPluginIndex_.begin(), hilogPluginIndex_.end());
88     supportPluginNameIndex_.insert(hidumpPluginIndex_.begin(), hidumpPluginIndex_.end());
89     supportPluginNameIndex_.insert(cpuPluginIndex_);
90     supportPluginNameIndex_.insert(networkPluginIndex_);
91     supportPluginNameIndex_.insert(diskioPluginIndex_);
92     supportPluginNameIndex_.insert(processPluginIndex_);
93     supportPluginNameIndex_.insert(arktsPluginIndex_);
94     supportPluginNameIndex_.insert(arktsPluginConfigIndex_);
95 }
96 
ParserFileSO(std::string & directory,const std::vector<std::string> & relativeFilePaths)97 void HtraceParser::ParserFileSO(std::string& directory, const std::vector<std::string>& relativeFilePaths)
98 {
99     for (const auto& filePath : relativeFilePaths) {
100         auto absoluteFilePath = filePath.substr(directory.length());
101         auto symbolsFile =
102             OHOS::Developtools::HiPerf::SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, absoluteFilePath);
103         symbolsFile->setSymbolsFilePath(directory);
104         symbolsFile->LoadSymbols(absoluteFilePath);
105         symbolsFiles_.emplace_back(std::move(symbolsFile));
106     }
107 }
108 
~HtraceParser()109 HtraceParser::~HtraceParser()
110 {
111     TS_LOGI("clockid 2 is for RealTime and 1 is for BootTime");
112 }
113 
ReparseSymbolFilesAndResymbolization(std::string & symbolsPath,std::vector<std::string> & symbolsPaths)114 bool HtraceParser::ReparseSymbolFilesAndResymbolization(std::string& symbolsPath,
115                                                         std::vector<std::string>& symbolsPaths)
116 {
117     std::vector<std::string> dir;
118     dir.emplace_back(symbolsPath);
119     auto parseStatus = false;
120     parseStatus = perfDataParser_->PerfReloadSymbolFiles(dir);
121     ParserFileSO(symbolsPath, symbolsPaths);
122     if (traceDataCache_->GetNativeHookFrameData()->Size() > 0) {
123         htraceNativeHookParser_->NativeHookReloadElfSymbolTable(symbolsFiles_);
124         parseStatus = true;
125     }
126     if (traceDataCache_->GetEbpfCallStack()->Size() > 0) {
127         ebpfDataParser_->EBPFReloadElfSymbolTable(symbolsFiles_);
128         parseStatus = true;
129     }
130     symbolsFiles_.clear();
131     return parseStatus;
132 }
133 
WaitForParserEnd()134 void HtraceParser::WaitForParserEnd()
135 {
136     if (parseThreadStarted_ || filterThreadStarted_) {
137         toExit_ = true;
138         while (!exited_) {
139             usleep(sleepDur_ * sleepDur_);
140         }
141     }
142     hasGotHeader_ = false;
143     htraceCpuDetailParser_->FilterAllEvents();
144     htraceNativeHookParser_->FinishParseNativeHookData();
145     htraceHiLogParser_->Finish();
146     htraceHidumpParser_->Finish();
147     cpuUsageParser_->Finish();
148     networkParser_->Finish();
149     processParser_->Finish();
150     diskIOParser_->Finish();
151     hisyseventParser_->Finish();
152     jsMemoryParser_->Finish();
153     // keep final upate perf and ebpf data time range
154     ebpfDataParser_->Finish();
155     perfDataParser_->Finish();
156     htraceNativeHookParser_->Finish();
157     htraceMemParser_->Finish();
158     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE,
159                                                                       dataSourceTypeTraceClockid_);
160     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_MEM, dataSourceTypeMemClockid_);
161     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HILOG,
162                                                                       dataSourceTypeHilogClockid_);
163     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NATIVEHOOK,
164                                                                       dataSourceTypeNativeHookClockid_);
165     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_FPS, dataSourceTypeFpsClockid_);
166     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NETWORK,
167                                                                       dataSourceTypeNetworkClockid_);
168     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_DISKIO,
169                                                                       dataSourceTypeDiskioClockid_);
170     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_CPU, dataSourceTypeCpuClockid_);
171     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_PROCESS,
172                                                                       dataSourceTypeProcessClockid_);
173     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HISYSEVENT,
174                                                                       dataSourceTypeHisyseventClockid_);
175     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_JSMEMORY,
176                                                                       dataSourceTypeJSMemoryClockid_);
177     traceDataCache_->GetDataSourceClockIdData()->Finish();
178     dataSegArray_.reset();
179     processedDataLen_ = 0;
180 }
181 
ParseTraceDataItem(const std::string & buffer)182 void HtraceParser::ParseTraceDataItem(const std::string& buffer)
183 {
184     int32_t head = rawDataHead_;
185     if (!traceDataCache_->supportThread_ || traceDataCache_->isSplitFile_) {
186         dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
187         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
188         ParserData(dataSegArray_[head], traceDataCache_->isSplitFile_);
189         return;
190     }
191     while (!toExit_) {
192         if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) {
193             usleep(sleepDur_);
194             continue;
195         }
196         dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
197         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
198         rawDataHead_ = (rawDataHead_ + 1) % maxSegArraySize;
199         break;
200     }
201     if (!parseThreadStarted_) {
202         parseThreadStarted_ = true;
203         int32_t tmp = traceDataCache_->parserThreadNum_;
204         while (tmp--) {
205             parserThreadCount_++;
206             std::thread ParseTypeThread(&HtraceParser::ParseThread, this);
207             ParseTypeThread.detach();
208             TS_LOGI("parser Thread:%d/%d start working ...\n", traceDataCache_->parserThreadNum_ - tmp,
209                     traceDataCache_->parserThreadNum_);
210         }
211     }
212     if (!filterThreadStarted_) {
213         filterThreadStarted_ = true;
214         std::thread FilterTypeThread(&HtraceParser::FilterThread, this);
215         TS_LOGI("FilterThread start working ...");
216         FilterTypeThread.detach();
217     }
218 }
219 
EnableFileSeparate(bool enabled)220 void HtraceParser::EnableFileSeparate(bool enabled)
221 {
222     jsMemoryParser_->EnableSaveFile(enabled);
223 }
FilterData(HtraceDataSegment & seg,bool isSplitFile)224 void HtraceParser::FilterData(HtraceDataSegment& seg, bool isSplitFile)
225 {
226     bool haveSplitSeg = false;
227     if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK) {
228         htraceNativeHookParser_->Parse(seg, haveSplitSeg);
229     } else if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG) {
230         htraceNativeHookParser_->ParseConfigInfo(seg);
231     } else if (seg.dataType == DATA_SOURCE_TYPE_TRACE) {
232         htraceCpuDetailParser_->FilterAllEventsReader();
233     } else if (seg.dataType == DATA_SOURCE_TYPE_MEM) {
234         htraceMemParser_->Parse(seg, seg.timeStamp, seg.clockId);
235     } else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) {
236         htraceHiLogParser_->Parse(seg.protoData, haveSplitSeg);
237     } else if (seg.dataType == DATA_SOURCE_TYPE_CPU) {
238         cpuUsageParser_->Parse(seg.protoData, seg.timeStamp);
239     } else if (seg.dataType == DATA_SOURCE_TYPE_FPS) {
240         htraceHidumpParser_->Parse(seg.protoData);
241         dataSourceTypeFpsClockid_ = htraceHidumpParser_->ClockId();
242     } else if (seg.dataType == DATA_SOURCE_TYPE_NETWORK) {
243         networkParser_->Parse(seg.protoData, seg.timeStamp);
244     } else if (seg.dataType == DATA_SOURCE_TYPE_PROCESS) {
245         processParser_->Parse(seg.protoData, seg.timeStamp);
246     } else if (seg.dataType == DATA_SOURCE_TYPE_DISKIO) {
247         diskIOParser_->Parse(seg.protoData, seg.timeStamp);
248     } else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY) {
249         jsMemoryParser_->Parse(seg.protoData, seg.timeStamp, traceDataCache_->SplitFileMinTime(),
250                                traceDataCache_->SplitFileMaxTime(), profilerPluginData_);
251     } else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY_CONFIG) {
252         jsMemoryParser_->ParseJSMemoryConfig(seg.protoData);
253     } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT) {
254         ProtoReader::HisyseventInfo_Reader hisyseventInfo(seg.protoData.data_, seg.protoData.size_);
255         hisyseventParser_->Parse(&hisyseventInfo, seg.timeStamp, haveSplitSeg);
256     } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT_CONFIG) {
257         ProtoReader::HisyseventConfig_Reader hisyseventConfig(seg.protoData.data_, seg.protoData.size_);
258         hisyseventParser_->Parse(&hisyseventConfig, seg.timeStamp);
259     } else if (seg.dataType == DATA_SOURCE_TYPE_MEM_CONFIG) {
260         htraceMemParser_->ParseMemoryConfig(seg);
261     }
262     if (traceDataCache_->isSplitFile_ && haveSplitSeg) {
263         mTraceDataHtrace_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
264     }
265     if (traceDataCache_->supportThread_ && !traceDataCache_->isSplitFile_) {
266         filterHead_ = (filterHead_ + 1) % maxSegArraySize;
267     }
268     seg.status = TS_PARSE_STATUS_INIT;
269 }
FilterThread()270 void HtraceParser::FilterThread()
271 {
272     TS_LOGI("filter thread start work!");
273     while (true) {
274         HtraceDataSegment& seg = dataSegArray_[filterHead_];
275         if (seg.status.load() == TS_PARSE_STATUS_INVALID) {
276             seg.status = TS_PARSE_STATUS_INIT;
277             filterHead_ = (filterHead_ + 1) % maxSegArraySize;
278             TS_LOGD("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_);
279             continue;
280         }
281         if (seg.status.load() != TS_PARSE_STATUS_PARSED) {
282             if (toExit_ && !parserThreadCount_) {
283                 TS_LOGI("exiting Filter Thread");
284                 exited_ = true;
285                 filterThreadStarted_ = false;
286                 TS_LOGI("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
287                         filterHead_, seg.status.load());
288                 return;
289             }
290             TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
291                     filterHead_, seg.status.load());
292             usleep(sleepDur_);
293             continue;
294         }
295         FilterData(seg, false);
296     }
297 }
298 
SpliteConfigData(const std::string & pluginName,const HtraceDataSegment & dataSeg)299 bool HtraceParser::SpliteConfigData(const std::string& pluginName, const HtraceDataSegment& dataSeg)
300 {
301     if (EndWith(pluginName, "arkts-plugin_config")) {
302         std::string dataString(dataSeg.seg->c_str(), dataSeg.seg->length());
303         arkTsConfigData_ = lenBuffer_ + dataString;
304         return true;
305     } else if (EndWith(pluginName, "config")) {
306         mTraceDataHtrace_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
307         return true;
308     }
309     return false;
310 }
311 
SpliteDataBySegment(DataIndex pluginNameIndex,HtraceDataSegment & dataSeg)312 bool HtraceParser::SpliteDataBySegment(DataIndex pluginNameIndex, HtraceDataSegment& dataSeg)
313 {
314     if (nativeHookPluginIndex_.count(pluginNameIndex) || ftracePluginIndex_.count(pluginNameIndex) ||
315         hilogPluginIndex_.count(pluginNameIndex) || hisyseventPluginIndex_ == pluginNameIndex) {
316         return false;
317     }
318     // need convert to Primary Time Plugin
319     if (pluginNameIndex == memPluginIndex_) {
320         dataSeg.timeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, dataSeg.timeStamp);
321         UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, dataSeg.timeStamp, dataSeg.timeStamp);
322     }
323     if (dataSeg.timeStamp >= traceDataCache_->SplitFileMinTime() &&
324         dataSeg.timeStamp <= traceDataCache_->SplitFileMaxTime()) {
325         mTraceDataHtrace_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
326     }
327     if (pluginNameIndex == arktsPluginConfigIndex_ || pluginNameIndex == arktsPluginIndex_) {
328         return false;
329     }
330     return true;
331 }
ParseDataByPluginName(HtraceDataSegment & dataSeg,DataIndex pulginNameIndex,const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,bool isSplitFile)332 void HtraceParser::ParseDataByPluginName(HtraceDataSegment& dataSeg,
333                                          DataIndex pulginNameIndex,
334                                          const ProtoReader::ProfilerPluginData_Reader& pluginDataZero,
335                                          bool isSplitFile)
336 {
337     if (nativeHookPluginIndex_.count(pulginNameIndex)) {
338         ParseNativeHook(dataSeg, isSplitFile);
339     } else if (pulginNameIndex == nativeHookConfigIndex_) {
340         ParseNativeHookConfig(dataSeg);
341     } else if (ftracePluginIndex_.count(pulginNameIndex)) { // ok
342         ParseFtrace(dataSeg);
343     } else if (pulginNameIndex == memPluginIndex_) {
344         ParseMemory(pluginDataZero, dataSeg);
345     } else if (hilogPluginIndex_.count(pulginNameIndex)) {
346         ParseHilog(dataSeg);
347     } else if (hidumpPluginIndex_.count(pulginNameIndex)) {
348         ParseFPS(dataSeg);
349     } else if (pulginNameIndex == cpuPluginIndex_) {
350         ParseCpuUsage(dataSeg);
351     } else if (pulginNameIndex == networkPluginIndex_) {
352         ParseNetwork(dataSeg);
353     } else if (pulginNameIndex == diskioPluginIndex_) {
354         ParseDiskIO(dataSeg);
355     } else if (pulginNameIndex == processPluginIndex_) {
356         ParseProcess(dataSeg);
357     } else if (pulginNameIndex == hisyseventPluginIndex_) {
358         ParseHisysevent(dataSeg);
359     } else if (pulginNameIndex == hisyseventPluginConfigIndex_) {
360         ParseHisyseventConfig(dataSeg);
361     } else if (pulginNameIndex == arktsPluginIndex_) {
362         ParseJSMemory(dataSeg, isSplitFile);
363     } else if (pulginNameIndex == arktsPluginConfigIndex_) {
364         ParseJSMemoryConfig(dataSeg);
365     } else if (pulginNameIndex == memoryPluginConfigIndex_) {
366         ParseMemoryConfig(dataSeg, pluginDataZero);
367     }
368 }
369 
ParserData(HtraceDataSegment & dataSeg,bool isSplitFile)370 void HtraceParser::ParserData(HtraceDataSegment& dataSeg, bool isSplitFile)
371 {
372     ProtoReader::ProfilerPluginData_Reader pluginDataZero(reinterpret_cast<const uint8_t*>(dataSeg.seg->c_str()),
373                                                           dataSeg.seg->length());
374     if (!pluginDataZero.has_name()) {
375         return;
376     }
377     auto pluginName = pluginDataZero.name().ToStdString();
378     auto pluginNameIndex = traceDataCache_->GetDataIndex(pluginName);
379     if (isSplitFile && SpliteConfigData(pluginName, dataSeg)) {
380         return;
381     }
382     if (pluginDataZero.has_tv_sec() && pluginDataZero.has_tv_nsec()) {
383         dataSeg.timeStamp = pluginDataZero.tv_sec() * SEC_TO_NS + pluginDataZero.tv_nsec();
384     }
385 
386     if (isSplitFile && SpliteDataBySegment(pluginNameIndex, dataSeg)) {
387         return;
388     }
389     if (supportPluginNameIndex_.count(pluginNameIndex)) {
390         dataSeg.protoData = pluginDataZero.data();
391         ParseDataByPluginName(dataSeg, pluginNameIndex, pluginDataZero, isSplitFile);
392     } else {
393 #if IS_WASM
394         TraceStreamer_Plugin_Out_Filter(reinterpret_cast<const char*>(pluginDataZero.data().data_),
395                                         pluginDataZero.data().size_, pluginName);
396 #endif
397         dataSeg.status = TS_PARSE_STATUS_INVALID;
398         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
399         return;
400     }
401     if (!traceDataCache_->supportThread_ || traceDataCache_->isSplitFile_) {
402         FilterData(dataSeg, isSplitFile);
403     }
404 }
ParseThread()405 void HtraceParser::ParseThread()
406 {
407     TS_LOGI("parser thread start work!\n");
408     while (true) {
409         int32_t head = GetNextSegment();
410         if (head < 0) {
411             if (head == ERROR_CODE_EXIT) {
412                 TS_LOGI("parse thread exit");
413                 return;
414             } else if (head == ERROR_CODE_NODATA) {
415                 continue;
416             }
417         }
418         HtraceDataSegment& dataSeg = dataSegArray_[head];
419         ParserData(dataSeg, false);
420     }
421 }
422 
ParseMemory(const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,HtraceDataSegment & dataSeg)423 void HtraceParser::ParseMemory(const ProtoReader::ProfilerPluginData_Reader& pluginDataZero, HtraceDataSegment& dataSeg)
424 {
425     BuiltinClocks clockId = TS_CLOCK_REALTIME;
426     auto clockIdTemp = pluginDataZero.clock_id();
427     if (clockIdTemp == ProtoReader::ProfilerPluginData_ClockId_CLOCKID_REALTIME) {
428         clockId = TS_CLOCK_REALTIME;
429     }
430     dataSourceTypeMemClockid_ = clockId;
431     dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
432     dataSeg.clockId = clockId;
433     dataSeg.status = TS_PARSE_STATUS_PARSED;
434 }
ParseHilog(HtraceDataSegment & dataSeg)435 void HtraceParser::ParseHilog(HtraceDataSegment& dataSeg)
436 {
437     dataSeg.dataType = DATA_SOURCE_TYPE_HILOG;
438     dataSourceTypeHilogClockid_ = TS_CLOCK_REALTIME;
439     dataSeg.status = TS_PARSE_STATUS_PARSED;
440 }
ParseNativeHookConfig(HtraceDataSegment & dataSeg)441 void HtraceParser::ParseNativeHookConfig(HtraceDataSegment& dataSeg)
442 {
443     dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG;
444     dataSeg.status = TS_PARSE_STATUS_PARSED;
445 }
ParseNativeHook(HtraceDataSegment & dataSeg,bool isSplitFile)446 void HtraceParser::ParseNativeHook(HtraceDataSegment& dataSeg, bool isSplitFile)
447 {
448     dataSourceTypeNativeHookClockid_ = TS_CLOCK_REALTIME;
449     dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK;
450     dataSeg.status = TS_PARSE_STATUS_PARSED;
451     if (isSplitFile) {
452         dataSourceType_ = DATA_SOURCE_TYPE_NATIVEHOOK;
453     }
454 }
ParseMemoryConfig(HtraceDataSegment & dataSeg,const ProtoReader::ProfilerPluginData_Reader & pluginDataZero)455 void HtraceParser::ParseMemoryConfig(HtraceDataSegment& dataSeg,
456                                      const ProtoReader::ProfilerPluginData_Reader& pluginDataZero)
457 {
458     if (pluginDataZero.has_sample_interval()) {
459         uint32_t sampleInterval = pluginDataZero.sample_interval();
460         traceDataCache_->GetTraceConfigData()->AppendNewData("memory_config", "sample_interval",
461                                                              std::to_string(sampleInterval));
462     }
463     dataSeg.dataType = DATA_SOURCE_TYPE_MEM_CONFIG;
464     dataSeg.status = TS_PARSE_STATUS_PARSED;
465 }
466 
ParseFtrace(HtraceDataSegment & dataSeg)467 void HtraceParser::ParseFtrace(HtraceDataSegment& dataSeg)
468 {
469     dataSeg.dataType = DATA_SOURCE_TYPE_TRACE;
470     ProtoReader::TracePluginResult_Reader tracePluginResult(dataSeg.protoData);
471     if (tracePluginResult.has_ftrace_cpu_stats()) {
472         auto cpuStats = *tracePluginResult.ftrace_cpu_stats();
473         ProtoReader::FtraceCpuStatsMsg_Reader ftraceCpuStatsMsg(cpuStats.data_, cpuStats.size_);
474         auto s = *ftraceCpuStatsMsg.per_cpu_stats();
475         ProtoReader::PerCpuStatsMsg_Reader perCpuStatsMsg(s.data_, s.size_);
476         TS_LOGD("s.overrun():%lu", perCpuStatsMsg.overrun());
477         TS_LOGD("s.dropped_events():%lu", perCpuStatsMsg.dropped_events());
478         auto clock = ftraceCpuStatsMsg.trace_clock().ToStdString();
479         if (clock == "boot") {
480             clock_ = TS_CLOCK_BOOTTIME;
481         } else if (clock == "mono") {
482             clock_ = TS_MONOTONIC;
483         } else {
484             TS_LOGI("invalid clock:%s", clock.c_str());
485             dataSeg.status = TS_PARSE_STATUS_INVALID;
486             return;
487         }
488         dataSeg.clockId = clock_;
489         dataSourceTypeTraceClockid_ = clock_;
490         dataSeg.status = TS_PARSE_STATUS_PARSED;
491         return;
492     }
493     bool haveSplitSeg = false;
494     dataSeg.clockId = clock_;
495     if (tracePluginResult.has_ftrace_cpu_detail()) {
496         htraceCpuDetailParser_->Parse(dataSeg, tracePluginResult, haveSplitSeg);
497         dataSeg.status = TS_PARSE_STATUS_PARSED;
498     }
499     if (tracePluginResult.has_symbols_detail()) {
500         htraceSymbolsDetailParser_->Parse(dataSeg.protoData); // has Event
501         haveSplitSeg = true;
502         dataSeg.status = TS_PARSE_STATUS_PARSED;
503     }
504     if (tracePluginResult.has_clocks_detail()) {
505         htraceClockDetailParser_->Parse(dataSeg.protoData); // has Event
506         haveSplitSeg = true;
507         dataSeg.status = TS_PARSE_STATUS_PARSED;
508     }
509     if (traceDataCache_->isSplitFile_ && haveSplitSeg) {
510         mTraceDataHtrace_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
511     }
512     dataSeg.status = TS_PARSE_STATUS_INVALID;
513 }
514 
ParseFPS(HtraceDataSegment & dataSeg)515 void HtraceParser::ParseFPS(HtraceDataSegment& dataSeg)
516 {
517     dataSeg.dataType = DATA_SOURCE_TYPE_FPS;
518     dataSeg.status = TS_PARSE_STATUS_PARSED;
519 }
520 
ParseCpuUsage(HtraceDataSegment & dataSeg)521 void HtraceParser::ParseCpuUsage(HtraceDataSegment& dataSeg)
522 {
523     dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
524     dataSeg.dataType = DATA_SOURCE_TYPE_CPU;
525     dataSeg.status = TS_PARSE_STATUS_PARSED;
526 }
ParseNetwork(HtraceDataSegment & dataSeg)527 void HtraceParser::ParseNetwork(HtraceDataSegment& dataSeg)
528 {
529     dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
530     dataSeg.dataType = DATA_SOURCE_TYPE_NETWORK;
531     dataSeg.status = TS_PARSE_STATUS_PARSED;
532 }
ParseDiskIO(HtraceDataSegment & dataSeg)533 void HtraceParser::ParseDiskIO(HtraceDataSegment& dataSeg)
534 {
535     dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
536     dataSeg.dataType = DATA_SOURCE_TYPE_DISKIO;
537     dataSeg.status = TS_PARSE_STATUS_PARSED;
538 }
539 
ParseProcess(HtraceDataSegment & dataSeg)540 void HtraceParser::ParseProcess(HtraceDataSegment& dataSeg)
541 {
542     dataSourceTypeProcessClockid_ = TS_CLOCK_BOOTTIME;
543     dataSeg.dataType = DATA_SOURCE_TYPE_PROCESS;
544     dataSeg.status = TS_PARSE_STATUS_PARSED;
545 }
546 
ParseHisysevent(HtraceDataSegment & dataSeg)547 void HtraceParser::ParseHisysevent(HtraceDataSegment& dataSeg)
548 {
549     dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
550     dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT;
551     dataSeg.status = TS_PARSE_STATUS_PARSED;
552 }
ParseHisyseventConfig(HtraceDataSegment & dataSeg)553 void HtraceParser::ParseHisyseventConfig(HtraceDataSegment& dataSeg)
554 {
555     dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
556     dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT_CONFIG;
557     dataSeg.status = TS_PARSE_STATUS_PARSED;
558 }
559 
ParseJSMemory(HtraceDataSegment & dataSeg,bool isSplitFile)560 void HtraceParser::ParseJSMemory(HtraceDataSegment& dataSeg, bool isSplitFile)
561 {
562     if (isSplitFile) {
563         dataSourceType_ = DATA_SOURCE_TYPE_JSMEMORY;
564         memcpy_s(&profilerPluginData_, sizeof(profilerPluginData_), dataSeg.seg->c_str(), dataSeg.seg->length());
565     }
566     dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
567     dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY;
568     dataSeg.status = TS_PARSE_STATUS_PARSED;
569 }
570 
ParseJSMemoryConfig(HtraceDataSegment & dataSeg)571 void HtraceParser::ParseJSMemoryConfig(HtraceDataSegment& dataSeg)
572 {
573     dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
574     dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY_CONFIG;
575     dataSeg.status = TS_PARSE_STATUS_PARSED;
576 }
577 
GetNextSegment()578 int32_t HtraceParser::GetNextSegment()
579 {
580     int32_t head;
581     std::lock_guard<std::mutex> muxLockGuard(htraceDataSegMux_);
582     head = parseHead_;
583     HtraceDataSegment& htraceDataSegmentSeg = dataSegArray_[head];
584     if (htraceDataSegmentSeg.status.load() != TS_PARSE_STATUS_SEPRATED) {
585         if (toExit_) {
586             parserThreadCount_--;
587             TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_);
588             TS_LOGI("seprateHead_x:\t%d, parseHead_:\t%d, filterHead_:\t%d status:%d\n", rawDataHead_, parseHead_,
589                     filterHead_, htraceDataSegmentSeg.status.load());
590             if (!parserThreadCount_ && !filterThreadStarted_) {
591                 exited_ = true;
592             }
593             return ERROR_CODE_EXIT;
594         }
595         usleep(sleepDur_);
596         return ERROR_CODE_NODATA;
597     }
598     parseHead_ = (parseHead_ + 1) % maxSegArraySize;
599     htraceDataSegmentSeg.status = TS_PARSE_STATUS_PARSING;
600     return head;
601 }
CalcEbpfCutOffset(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)602 bool HtraceParser::CalcEbpfCutOffset(std::deque<uint8_t>::iterator& packagesBegin, size_t& currentLength)
603 {
604     auto standaloneDataLength = profilerDataLength_ - packetHeaderLength_;
605     if (traceDataCache_->isSplitFile_ && !parsedEbpfOver_) {
606         if (!hasInitEbpfPublicData_) {
607             // Record the offset of Hiperf's 1024-byte header relative to the entire file.
608             ebpfDataParser_->SetEbpfDataOffset(processedDataLen_);
609             ebpfDataParser_->SetSpliteTimeRange(traceDataCache_->SplitFileMinTime(),
610                                                 traceDataCache_->SplitFileMaxTime());
611             parsedFileOffset_ += profilerDataLength_ - packetHeaderLength_;
612             hasInitEbpfPublicData_ = true;
613         }
614         parsedEbpfOver_ = ebpfDataParser_->AddAndSplitEbpfData(packagesBuffer_);
615         if (parsedEbpfOver_) {
616             profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
617             hasGotHeader_ = false;
618             processedDataLen_ += standaloneDataLength;
619         }
620         return false;
621     }
622     if (!traceDataCache_->isSplitFile_ && packagesBuffer_.size() >= standaloneDataLength) {
623         ebpfDataParser_->InitAndParseEbpfData(packagesBuffer_, standaloneDataLength);
624         currentLength -= standaloneDataLength;
625         packagesBegin += standaloneDataLength;
626         profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
627         hasGotHeader_ = false;
628         return true;
629     }
630     return false;
631 }
632 
GetHeaderAndUpdateLengthMark(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)633 bool HtraceParser::GetHeaderAndUpdateLengthMark(std::deque<uint8_t>::iterator& packagesBegin, size_t& currentLength)
634 {
635     if (!hasGotHeader_) {
636         if (!InitProfilerTraceFileHeader()) {
637             return false;
638         }
639         packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + packetHeaderLength_);
640         processedDataLen_ += packetHeaderLength_;
641         currentLength -= packetHeaderLength_;
642         packagesBegin += packetHeaderLength_;
643         parsedFileOffset_ += packetHeaderLength_;
644         htraceCurentLength_ = profilerDataLength_ - packetHeaderLength_;
645         hasGotHeader_ = true;
646         if (!currentLength) {
647             return false;
648         }
649     }
650     return true;
651 }
652 #if IS_WASM
ParseSDKData()653 bool HtraceParser::ParseSDKData()
654 {
655     if (packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_) {
656         auto thirdPartySize = profilerDataLength_ - packetHeaderLength_;
657         auto buffer = std::make_unique<uint8_t[]>(thirdPartySize).get();
658         std::copy(packagesBuffer_.begin(), packagesBuffer_.begin() + thirdPartySize, buffer);
659         TraceStreamer_Plugin_Out_Filter(reinterpret_cast<const char*>(buffer), thirdPartySize, standalonePluginName_);
660         return true;
661     }
662     return false;
663 }
664 #endif
665 
ParseSegLengthAndEnsureSegDataEnough(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)666 bool HtraceParser::ParseSegLengthAndEnsureSegDataEnough(std::deque<uint8_t>::iterator& packagesBegin,
667                                                         size_t& currentLength)
668 {
669     std::string bufferLine;
670     if (!hasGotSegLength_) {
671         if (currentLength < packetSegLength_) {
672             return false;
673         }
674         bufferLine.assign(packagesBegin, packagesBegin + packetSegLength_);
675         const uint32_t* len = reinterpret_cast<const uint32_t*>(bufferLine.data());
676         nextLength_ = *len;
677         lenBuffer_ = bufferLine;
678         htraceLength_ += nextLength_ + packetSegLength_;
679         hasGotSegLength_ = true;
680         currentLength -= packetSegLength_;
681         packagesBegin += packetSegLength_;
682         parsedFileOffset_ += packetSegLength_;
683         splitFileOffset_ = profilerDataLength_ - htraceCurentLength_;
684         htraceCurentLength_ -= packetSegLength_;
685     }
686     if (currentLength < nextLength_) {
687         return false;
688     }
689     return true;
690 }
ParseDataRecursively(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)691 bool HtraceParser::ParseDataRecursively(std::deque<uint8_t>::iterator& packagesBegin, size_t& currentLength)
692 {
693     TS_CHECK_TRUE_RET(GetHeaderAndUpdateLengthMark(packagesBegin, currentLength), false);
694     if (profilerDataType_ == ProfilerTraceFileHeader::HIPERF_DATA) {
695         return ParseHiperfData(packagesBegin, currentLength);
696     }
697     if (profilerDataType_ == ProfilerTraceFileHeader::STANDALONE_DATA) {
698         if (EBPF_PLUGIN_NAME.compare(standalonePluginName_) == 0) {
699             return CalcEbpfCutOffset(packagesBegin, currentLength);
700         } else {
701 #if IS_WASM
702             TS_CHECK_TRUE_RET(ParseSDKData(), false); // 三方sdk逻辑待验证。
703 #endif
704         }
705     }
706     std::string bufferLine;
707     while (true) {
708         TS_CHECK_TRUE_RET(ParseSegLengthAndEnsureSegDataEnough(packagesBegin, currentLength), true);
709         bufferLine.assign(packagesBegin, packagesBegin + nextLength_);
710         ParseTraceDataItem(bufferLine);
711         hasGotSegLength_ = false;
712         packagesBegin += nextLength_;
713         currentLength -= nextLength_;
714         parsedFileOffset_ += nextLength_;
715         if (nextLength_ > htraceCurentLength_) {
716             TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%" PRIu64 "", nextLength_,
717                     htraceCurentLength_);
718         }
719         htraceCurentLength_ -= nextLength_;
720         if (htraceCurentLength_ == 0) {
721             hasGotHeader_ = false;
722             processedDataLen_ += packagesBegin - packagesBuffer_.begin();
723             packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
724             profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
725             TS_LOGD("read proto finished!");
726             return ParseDataRecursively(packagesBegin, currentLength);
727         }
728     }
729     return true;
730 }
731 
ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size,bool isFinish)732 void HtraceParser::ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, bool isFinish)
733 {
734     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
735     auto packagesBegin = packagesBuffer_.begin();
736     auto currentLength = packagesBuffer_.size();
737     if (ParseDataRecursively(packagesBegin, currentLength)) {
738         processedDataLen_ += packagesBegin - packagesBuffer_.begin();
739         packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
740     }
741     return;
742 }
ParseHiperfData(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)743 bool HtraceParser::ParseHiperfData(std::deque<uint8_t>::iterator& packagesBegin, size_t& currentLength)
744 {
745     if (!traceDataCache_->isSplitFile_) {
746         if (packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_) {
747             auto size = profilerDataLength_ - packetHeaderLength_;
748             (void)perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size, processedDataLen_, false, true);
749             currentLength -= size;
750             packagesBegin += size;
751             profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
752             hasGotHeader_ = false;
753             return true;
754         }
755         return false;
756     }
757 
758     bool isFinish = perfProcessedLen_ + packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_;
759     auto size = packagesBuffer_.size();
760     if (isFinish) {
761         size = profilerDataLength_ - packetHeaderLength_ - perfProcessedLen_;
762     }
763     auto ret = perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size, processedDataLen_, true, isFinish);
764     perfProcessedLen_ += ret;
765     currentLength -= ret;
766     packagesBegin += ret;
767     if (isFinish) {
768         profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
769         hasGotHeader_ = false;
770     }
771     return true;
772 }
StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size,int32_t isFinish)773 void HtraceParser::StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, int32_t isFinish)
774 {
775     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
776     if (!traceDataCache_->isSplitFile_) {
777         return;
778     }
779 
780     uint64_t length = packagesBuffer_.size();
781     auto ret = perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, length, 0, true, isFinish);
782     perfProcessedLen_ += ret;
783     processedDataLen_ += ret;
784     packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + ret);
785     return;
786 }
TraceDataSegmentEnd(bool isSplitFile)787 void HtraceParser::TraceDataSegmentEnd(bool isSplitFile)
788 {
789     perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, packagesBuffer_.size(), 0, isSplitFile, true);
790     packagesBuffer_.clear();
791     return;
792 }
793 
InitProfilerTraceFileHeader()794 bool HtraceParser::InitProfilerTraceFileHeader()
795 {
796     if (packagesBuffer_.size() < packetHeaderLength_) {
797         TS_LOGI("buffer size less than profiler trace file header");
798         return false;
799     }
800     uint8_t buffer[packetHeaderLength_];
801     (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
802     int32_t i = 0;
803     for (auto it = packagesBuffer_.begin(); it != packagesBuffer_.begin() + packetHeaderLength_; ++it, ++i) {
804         buffer[i] = *it;
805     }
806     ProfilerTraceFileHeader* pHeader = reinterpret_cast<ProfilerTraceFileHeader*>(buffer);
807     if (pHeader->data.length <= packetHeaderLength_ || pHeader->data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
808         TS_LOGE("Profiler Trace data is truncated or invalid magic! len = %" PRIu64 ", maigc = %" PRIx64 "",
809                 pHeader->data.length, pHeader->data.magic);
810         return false;
811     }
812     if (pHeader->data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) {
813         perfDataParser_->RecordPerfProfilerHeader(buffer, packetHeaderLength_);
814     } else if (pHeader->data.dataType == ProfilerTraceFileHeader::STANDALONE_DATA &&
815                EBPF_PLUGIN_NAME.compare(pHeader->data.standalonePluginName) == 0) {
816         ebpfDataParser_->RecordEbpfProfilerHeader(buffer, packetHeaderLength_);
817     } else {
818         auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, packetHeaderLength_);
819         if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
820             TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %" PRIx64 "", ret,
821                     profilerTraceFileHeader_.data.magic);
822             return false;
823         }
824     }
825     profilerDataLength_ = pHeader->data.length;
826     profilerDataType_ = pHeader->data.dataType;
827     memcpy_s(standalonePluginName_, sizeof(standalonePluginName_), pHeader->data.standalonePluginName,
828              sizeof(standalonePluginName_));
829 
830     TS_LOGI("magic = %" PRIx64 ", length = %" PRIu64 ", dataType = %x, boottime = %" PRIu64 "", pHeader->data.magic,
831             pHeader->data.length, pHeader->data.dataType, pHeader->data.boottime);
832 #if IS_WASM
833     const int32_t DATA_TYPE_CLOCK = 100;
834     TraceStreamer_Plugin_Out_SendData(reinterpret_cast<char*>(buffer), packetHeaderLength_, DATA_TYPE_CLOCK);
835 #endif
836     htraceClockDetailParser_->Parse(pHeader);
837     return true;
838 }
839 } // namespace TraceStreamer
840 } // namespace SysTuning
841