• 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 #ifdef SUPPORTTHREAD
51       supportThread_(true),
52       dataSegArray_(std::make_unique<HtraceDataSegment[]>(MAX_SEG_ARRAY_SIZE))
53 #else
54       ebpfDataParser_(std::make_unique<EbpfDataParser>(dataCache, filters)),
55       dataSegArray_(std::make_unique<HtraceDataSegment[]>(1))
56 #endif
57 {
58 }
GetSymbols(std::unique_ptr<ElfFile> elfPtr,std::shared_ptr<ElfSymbolTable> symbols,const std::string & filename)59 void HtraceParser::GetSymbols(std::unique_ptr<ElfFile> elfPtr,
60                               std::shared_ptr<ElfSymbolTable> symbols,
61                               const std::string& filename)
62 {
63     symbols->filePathIndex = traceDataCache_->dataDict_.GetStringIndex(filename.c_str());
64     symbols->textVaddr = (std::numeric_limits<uint64_t>::max)();
65     for (auto& item : elfPtr->phdrs_) {
66         if ((item->type_ == PT_LOAD) && (item->flags_ & PF_X)) {
67             // find the min addr
68             if (symbols->textVaddr != (std::min)(symbols->textVaddr, item->vaddr_)) {
69                 symbols->textVaddr = (std::min)(symbols->textVaddr, item->vaddr_);
70                 symbols->textOffset = item->offset_;
71             }
72         }
73     }
74     if (symbols->textVaddr == (std::numeric_limits<uint64_t>::max)()) {
75         TS_LOGE("GetSymbols get textVaddr failed");
76         return;
77     }
78 
79     std::string symSecName;
80     std::string strSecName;
81     if (elfPtr->shdrs_.find(".symtab") != elfPtr->shdrs_.end()) {
82         symSecName = ".symtab";
83         strSecName = ".strtab";
84     } else if (elfPtr->shdrs_.find(".dynsym") != elfPtr->shdrs_.end()) {
85         symSecName = ".dynsym";
86         strSecName = ".dynstr";
87     } else {
88         return;
89     }
90     const auto& sym = elfPtr->shdrs_[static_cast<const std::string>(symSecName)];
91     const uint8_t* symData = elfPtr->GetSectionData(sym->secIndex_);
92     const auto& str = elfPtr->shdrs_[static_cast<const std::string>(strSecName)];
93     const uint8_t* strData = elfPtr->GetSectionData(str->secIndex_);
94 
95     if (!sym->secSize_ || !str->secSize_) {
96         TS_LOGE(
97             "GetSymbols get section size failed, \
98             sym size: %" PRIu64 ", str size: %" PRIu64 "",
99             sym->secSize_, str->secSize_);
100         return;
101     }
102     symbols->symEntSize = sym->secEntrySize_;
103     std::string symTable(symData, symData + sym->secSize_);
104     symbols->symTable = std::move(symTable);
105     std::string strTable(strData, strData + str->secSize_);
106     symbols->strTable = std::move(strTable);
107 }
108 
ParserFileSO(std::string & directory,std::vector<std::string> & relativeFilePaths)109 bool HtraceParser::ParserFileSO(std::string& directory, std::vector<std::string>& relativeFilePaths)
110 {
111     elfSymbolTables_ = std::make_shared<std::vector<std::shared_ptr<ElfSymbolTable>>>();
112     std::cout << "start Parser File so" << std::endl;
113     for (auto relativeFilePath : relativeFilePaths) {
114         if (relativeFilePath.compare(0, directory.length(), directory)) {
115             TS_LOGI("%s not in directory %s", relativeFilePath.c_str(), directory.c_str());
116             continue;
117         }
118         std::unique_ptr<ElfFile> elfFile = ElfFile::MakeUnique(relativeFilePath);
119         if (elfFile == nullptr) {
120             TS_LOGI("elf %s load failed", relativeFilePath.c_str());
121             continue;
122         } else {
123             TS_LOGI("loaded elf %s", relativeFilePath.c_str());
124         }
125         auto symbolInfo = std::make_shared<ElfSymbolTable>();
126         auto absoluteFilePath = relativeFilePath.substr(directory.length());
127         GetSymbols(std::move(elfFile), symbolInfo, absoluteFilePath);
128         elfSymbolTables_->emplace_back(symbolInfo);
129     }
130     if (!elfSymbolTables_->size()) {
131         return false;
132     }
133     return true;
134 }
135 
~HtraceParser()136 HtraceParser::~HtraceParser()
137 {
138     TS_LOGI("clockid 2 is for RealTime and 1 is for BootTime");
139 }
140 
ReparseSymbolFilesAndResymbolization(std::string & symbolsPath,std::vector<std::string> & symbolsPaths)141 bool HtraceParser::ReparseSymbolFilesAndResymbolization(std::string& symbolsPath,
142                                                         std::vector<std::string>& symbolsPaths)
143 {
144     auto parsePerfStatus = false;
145     std::vector<std::string> dir;
146     dir.emplace_back(symbolsPath);
147     parsePerfStatus = perfDataParser_->PerfReloadSymbolFiles(dir);
148     auto parseFileSOStatus = ParserFileSO(symbolsPath, symbolsPaths);
149     if (!parseFileSOStatus) {
150         elfSymbolTables_.reset();
151         return parsePerfStatus;
152     }
153     if (htraceNativeHookParser_->SupportImportSymbolTable()) {
154         htraceNativeHookParser_->NativeHookReloadElfSymbolTable(elfSymbolTables_);
155     }
156     if (ebpfDataParser_->SupportImportSymbolTable()) {
157         ebpfDataParser_->EBPFReloadElfSymbolTable(elfSymbolTables_);
158     }
159     elfSymbolTables_.reset();
160     return true;
161 }
WaitForParserEnd()162 void HtraceParser::WaitForParserEnd()
163 {
164     if (parseThreadStarted_ || filterThreadStarted_) {
165         toExit_ = true;
166         while (!exited_) {
167             usleep(sleepDur_ * sleepDur_);
168         }
169     }
170     htraceCpuDetailParser_->FilterAllEvents();
171     htraceNativeHookParser_->FinishParseNativeHookData();
172     htraceHiLogParser_->Finish();
173     htraceHidumpParser_->Finish();
174     cpuUsageParser_->Finish();
175     networkParser_->Finish();
176     processParser_->Finish();
177     diskIOParser_->Finish();
178     hisyseventParser_->Finish();
179     jsMemoryParser_->Finish();
180     // keep final upate perf and ebpf data time range
181     ebpfDataParser_->Finish();
182     perfDataParser_->Finish();
183     htraceNativeHookParser_->Finish();
184     htraceMemParser_->Finish();
185     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE,
186                                                                       dataSourceTypeTraceClockid_);
187     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_MEM, dataSourceTypeMemClockid_);
188     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HILOG,
189                                                                       dataSourceTypeHilogClockid_);
190     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NATIVEHOOK,
191                                                                       dataSourceTypeNativeHookClockid_);
192     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_FPS, dataSourceTypeFpsClockid_);
193     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NETWORK,
194                                                                       dataSourceTypeNetworkClockid_);
195     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_DISKIO,
196                                                                       dataSourceTypeDiskioClockid_);
197     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_CPU, dataSourceTypeCpuClockid_);
198     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_PROCESS,
199                                                                       dataSourceTypeProcessClockid_);
200     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HISYSEVENT,
201                                                                       dataSourceTypeHisyseventClockid_);
202     traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_JSMEMORY,
203                                                                       dataSourceTypeJSMemoryClockid_);
204     traceDataCache_->GetDataSourceClockIdData()->Finish();
205     dataSegArray_.reset();
206 }
207 
ParseTraceDataItem(const std::string & buffer)208 void HtraceParser::ParseTraceDataItem(const std::string& buffer)
209 {
210     int32_t head = rawDataHead_;
211     if (!supportThread_) {
212         dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
213         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
214         ParserData(dataSegArray_[head]);
215         return;
216     }
217     while (!toExit_) {
218         if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) {
219             usleep(sleepDur_);
220             continue;
221         }
222         dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
223         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
224         rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE;
225         break;
226     }
227     if (!parseThreadStarted_) {
228         parseThreadStarted_ = true;
229         int32_t tmp = maxThread_;
230         while (tmp--) {
231             parserThreadCount_++;
232             std::thread ParseTypeThread(&HtraceParser::ParseThread, this);
233             ParseTypeThread.detach();
234             TS_LOGD("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_);
235         }
236     }
237 }
238 
EnableFileSeparate(bool enabled)239 void HtraceParser::EnableFileSeparate(bool enabled)
240 {
241     jsMemoryParser_->EnableSaveFile(enabled);
242 }
FilterData(HtraceDataSegment & seg)243 void HtraceParser::FilterData(HtraceDataSegment& seg)
244 {
245     if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK) {
246         htraceNativeHookParser_->Parse(seg);
247     } else if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG) {
248         htraceNativeHookParser_->ParseConfigInfo(seg);
249     } else if (seg.dataType == DATA_SOURCE_TYPE_TRACE) {
250         ProtoReader::TracePluginResult_Reader tracePluginResult(seg.protoData);
251         if (tracePluginResult.has_ftrace_cpu_detail()) {
252             htraceCpuDetailParser_->Parse(seg, seg.clockId);
253         }
254         if (tracePluginResult.has_symbols_detail()) {
255             htraceSymbolsDetailParser_->Parse(seg.protoData); // has Event
256         }
257         if (tracePluginResult.has_clocks_detail()) {
258             htraceClockDetailParser_->Parse(seg.protoData); // has Event
259         }
260     } else if (seg.dataType == DATA_SOURCE_TYPE_MEM) {
261         htraceMemParser_->Parse(seg, seg.timeStamp, seg.clockId);
262     } else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) {
263         htraceHiLogParser_->Parse(seg.protoData);
264     } else if (seg.dataType == DATA_SOURCE_TYPE_CPU) {
265         cpuUsageParser_->Parse(seg.protoData, seg.timeStamp);
266     } else if (seg.dataType == DATA_SOURCE_TYPE_FPS) {
267         htraceHidumpParser_->Parse(seg.protoData);
268         dataSourceTypeFpsClockid_ = htraceHidumpParser_->ClockId();
269     } else if (seg.dataType == DATA_SOURCE_TYPE_NETWORK) {
270         networkParser_->Parse(seg.protoData, seg.timeStamp);
271     } else if (seg.dataType == DATA_SOURCE_TYPE_PROCESS) {
272         processParser_->Parse(seg.protoData, seg.timeStamp);
273     } else if (seg.dataType == DATA_SOURCE_TYPE_DISKIO) {
274         diskIOParser_->Parse(seg.protoData, seg.timeStamp);
275     } else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY) {
276         jsMemoryParser_->Parse(seg.protoData, seg.timeStamp);
277     } else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY_CONFIG) {
278         jsMemoryParser_->ParseJSMemoryConfig(seg.protoData);
279     } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT) {
280         ProtoReader::HisyseventInfo_Reader hisyseventInfo(seg.protoData.data_, seg.protoData.size_);
281         hisyseventParser_->Parse(&hisyseventInfo, seg.timeStamp);
282     } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT_CONFIG) {
283         ProtoReader::HisyseventConfig_Reader hisyseventConfig(seg.protoData.data_, seg.protoData.size_);
284         hisyseventParser_->Parse(&hisyseventConfig, seg.timeStamp);
285     } else if (seg.dataType == DATA_SOURCE_TYPE_MEM_CONFIG) {
286         htraceMemParser_->ParseMemoryConfig(seg);
287     }
288     if (supportThread_) {
289         filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE;
290     }
291     seg.status = TS_PARSE_STATUS_INIT;
292 }
FilterThread()293 void HtraceParser::FilterThread()
294 {
295     TS_LOGI("filter thread start work!");
296     while (1) {
297         HtraceDataSegment& seg = dataSegArray_[filterHead_];
298         if (seg.status.load() == TS_PARSE_STATUS_INVALID) {
299             seg.status = TS_PARSE_STATUS_INIT;
300             filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE;
301             streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
302             TS_LOGD("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_);
303             continue;
304         }
305         if (seg.status.load() != TS_PARSE_STATUS_PARSED) {
306             if (toExit_ && !parserThreadCount_) {
307                 TS_LOGI("exiting Filter Thread");
308                 exited_ = true;
309                 filterThreadStarted_ = false;
310                 TS_LOGI("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
311                         filterHead_, seg.status.load());
312                 return;
313             }
314             TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
315                     filterHead_, seg.status.load());
316             usleep(sleepDur_);
317             continue;
318         }
319         FilterData(seg);
320     }
321 }
ParserData(HtraceDataSegment & dataSeg)322 void HtraceParser::ParserData(HtraceDataSegment& dataSeg)
323 {
324     ProtoReader::ProfilerPluginData_Reader pluginDataZero(reinterpret_cast<const uint8_t*>(dataSeg.seg->c_str()),
325                                                           dataSeg.seg->length());
326     std::string pluginName;
327     if (pluginDataZero.has_name()) {
328         pluginName = pluginDataZero.name().ToStdString();
329     }
330     if (pluginDataZero.has_tv_sec() && pluginDataZero.has_tv_nsec()) {
331         dataSeg.timeStamp = pluginDataZero.tv_sec() * SEC_TO_NS + pluginDataZero.tv_nsec();
332     }
333     if (pluginName == "nativehook" || pluginName == "hookdaemon") {
334         dataSourceTypeNativeHookClockid_ = TS_CLOCK_REALTIME;
335         dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK;
336         dataSeg.protoData = pluginDataZero.data();
337     } else if (pluginName == "nativehook_config") {
338         dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG;
339         dataSeg.protoData = pluginDataZero.data();
340     } else if (pluginDataZero.name().ToStdString() == "ftrace-plugin" ||
341                pluginDataZero.name().ToStdString() == "/data/local/tmp/libftrace_plugin.z.so") { // ok
342         dataSeg.dataType = DATA_SOURCE_TYPE_TRACE;
343         dataSeg.protoData = pluginDataZero.data();
344         ParseFtrace(dataSeg);
345     } else if (pluginName == "memory-plugin") {
346         dataSeg.protoData = pluginDataZero.data();
347         dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
348         ParseMemory(&pluginDataZero, dataSeg);
349     } else if (pluginName == "hilog-plugin" || pluginName == "/data/local/tmp/libhilogplugin.z.so") {
350         dataSeg.protoData = pluginDataZero.data();
351         ParseHilog(dataSeg);
352     } else if (pluginName == "hidump-plugin" || pluginName == "/data/local/tmp/libhidumpplugin.z.so") {
353         dataSeg.protoData = pluginDataZero.data();
354         ParseFPS(dataSeg);
355     } else if (pluginName == "cpu-plugin") {
356         dataSeg.protoData = pluginDataZero.data();
357         ParseCpuUsage(dataSeg);
358     } else if (pluginName == "network-plugin") {
359         dataSeg.protoData = pluginDataZero.data();
360         ParseNetwork(dataSeg);
361     } else if (pluginName == "diskio-plugin") {
362         dataSeg.protoData = pluginDataZero.data();
363         ParseDiskIO(dataSeg);
364     } else if (pluginName == "process-plugin") {
365         dataSeg.protoData = pluginDataZero.data();
366         ParseProcess(dataSeg);
367     } else if (pluginName == "hisysevent-plugin") {
368         dataSeg.protoData = pluginDataZero.data();
369         ParseHisysevent(dataSeg);
370     } else if (pluginName == "hisysevent-plugin_config") {
371         dataSeg.protoData = pluginDataZero.data();
372         ParseHisyseventConfig(dataSeg);
373     } else if (pluginName == "arkts-plugin") {
374         dataSeg.protoData = pluginDataZero.data();
375         ParseJSMemory(dataSeg);
376     } else if (pluginName == "arkts-plugin_config") {
377         dataSeg.protoData = pluginDataZero.data();
378         ParseJSMemoryConfig(dataSeg);
379     } else if (pluginName == "memory-plugin_config") {
380         if (pluginDataZero.has_sample_interval()) {
381             uint32_t sampleInterval = pluginDataZero.sample_interval();
382             traceDataCache_->GetTraceConfigData()->AppendNewData("memory_config", "sample_interval",
383                                                                  std::to_string(sampleInterval));
384         }
385         dataSeg.dataType = DATA_SOURCE_TYPE_MEM_CONFIG;
386         dataSeg.protoData = pluginDataZero.data();
387     } else {
388 #if IS_WASM
389         TraceStreamer_Plugin_Out_Filter(reinterpret_cast<const char*>(pluginDataZero.data().data_),
390                                         pluginDataZero.data().size_, pluginName);
391 #endif
392         dataSeg.status = TS_PARSE_STATUS_INVALID;
393         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
394         return;
395     }
396     if (!supportThread_) { // do it only in wasm mode, wasm noThead_ will be true
397         if (dataSeg.status == TS_PARSE_STATUS_INVALID) {
398             streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
399             return;
400         }
401         FilterData(dataSeg);
402     }
403 }
ParseThread()404 void HtraceParser::ParseThread()
405 {
406     TS_LOGI("parser thread start work!\n");
407     while (1) {
408         if (supportThread_ && !filterThreadStarted_) {
409             filterThreadStarted_ = true;
410             std::thread ParserThread(&HtraceParser::FilterThread, this);
411             TS_LOGD("FilterThread start working ...\n");
412             ParserThread.detach();
413         }
414         int32_t head = GetNextSegment();
415         if (head < 0) {
416             if (head == ERROR_CODE_EXIT) {
417                 TS_LOGI("parse thread exit\n");
418                 return;
419             } else if (head == ERROR_CODE_NODATA) {
420                 continue;
421             }
422         }
423         HtraceDataSegment& dataSeg = dataSegArray_[head];
424         ParserData(dataSeg);
425     }
426 }
427 
ParseMemory(ProtoReader::ProfilerPluginData_Reader * pluginDataZero,HtraceDataSegment & dataSeg)428 void HtraceParser::ParseMemory(ProtoReader::ProfilerPluginData_Reader* pluginDataZero, HtraceDataSegment& dataSeg)
429 {
430     BuiltinClocks clockId = TS_CLOCK_REALTIME;
431     auto clockIdTemp = pluginDataZero->clock_id();
432     if (clockIdTemp == ProtoReader::ProfilerPluginData_ClockId_CLOCKID_REALTIME) {
433         clockId = TS_CLOCK_REALTIME;
434     }
435     dataSourceTypeMemClockid_ = clockId;
436     dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
437     dataSeg.clockId = clockId;
438     dataSeg.status = TS_PARSE_STATUS_PARSED;
439 }
ParseHilog(HtraceDataSegment & dataSeg)440 void HtraceParser::ParseHilog(HtraceDataSegment& dataSeg)
441 {
442     dataSeg.dataType = DATA_SOURCE_TYPE_HILOG;
443     dataSourceTypeHilogClockid_ = TS_CLOCK_REALTIME;
444     dataSeg.status = TS_PARSE_STATUS_PARSED;
445 }
446 
ParseFtrace(HtraceDataSegment & dataSeg)447 void HtraceParser::ParseFtrace(HtraceDataSegment& dataSeg)
448 {
449     ProtoReader::TracePluginResult_Reader tracePluginResult(dataSeg.protoData);
450     if (tracePluginResult.has_ftrace_cpu_stats()) {
451         auto cpuStats = *tracePluginResult.ftrace_cpu_stats();
452         ProtoReader::FtraceCpuStatsMsg_Reader ftraceCpuStatsMsg(cpuStats.data_, cpuStats.size_);
453         auto s = *ftraceCpuStatsMsg.per_cpu_stats();
454         ProtoReader::PerCpuStatsMsg_Reader perCpuStatsMsg(s.data_, s.size_);
455         TS_LOGD("s.overrun():%lu", perCpuStatsMsg.overrun());
456         TS_LOGD("s.dropped_events():%lu", perCpuStatsMsg.dropped_events());
457         auto clock = ftraceCpuStatsMsg.trace_clock().ToStdString();
458         if (clock == "boot") {
459             clock_ = TS_CLOCK_BOOTTIME;
460         } else if (clock == "mono") {
461             clock_ = TS_MONOTONIC;
462         } else {
463             TS_LOGI("invalid clock:%s", clock.c_str());
464             dataSeg.status = TS_PARSE_STATUS_INVALID;
465             return;
466         }
467         dataSeg.clockId = clock_;
468         dataSeg.status = TS_PARSE_STATUS_PARSED;
469         return;
470     }
471     dataSeg.clockId = clock_;
472     dataSourceTypeTraceClockid_ = clock_;
473     if (tracePluginResult.has_clocks_detail() || tracePluginResult.has_ftrace_cpu_detail() ||
474         tracePluginResult.has_symbols_detail()) {
475         dataSeg.status = TS_PARSE_STATUS_PARSED;
476         return;
477     }
478     dataSeg.status = TS_PARSE_STATUS_INVALID;
479 }
480 
ParseFPS(HtraceDataSegment & dataSeg)481 void HtraceParser::ParseFPS(HtraceDataSegment& dataSeg)
482 {
483     dataSeg.dataType = DATA_SOURCE_TYPE_FPS;
484     dataSeg.status = TS_PARSE_STATUS_PARSED;
485 }
486 
ParseCpuUsage(HtraceDataSegment & dataSeg)487 void HtraceParser::ParseCpuUsage(HtraceDataSegment& dataSeg)
488 {
489     dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
490     dataSeg.dataType = DATA_SOURCE_TYPE_CPU;
491     dataSeg.status = TS_PARSE_STATUS_PARSED;
492 }
ParseNetwork(HtraceDataSegment & dataSeg)493 void HtraceParser::ParseNetwork(HtraceDataSegment& dataSeg)
494 {
495     dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
496     dataSeg.dataType = DATA_SOURCE_TYPE_NETWORK;
497     dataSeg.status = TS_PARSE_STATUS_PARSED;
498 }
ParseDiskIO(HtraceDataSegment & dataSeg)499 void HtraceParser::ParseDiskIO(HtraceDataSegment& dataSeg)
500 {
501     dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME;
502     dataSeg.dataType = DATA_SOURCE_TYPE_DISKIO;
503     dataSeg.status = TS_PARSE_STATUS_PARSED;
504 }
505 
ParseProcess(HtraceDataSegment & dataSeg)506 void HtraceParser::ParseProcess(HtraceDataSegment& dataSeg)
507 {
508     dataSourceTypeProcessClockid_ = TS_CLOCK_BOOTTIME;
509     dataSeg.dataType = DATA_SOURCE_TYPE_PROCESS;
510     dataSeg.status = TS_PARSE_STATUS_PARSED;
511 }
512 
ParseHisysevent(HtraceDataSegment & dataSeg)513 void HtraceParser::ParseHisysevent(HtraceDataSegment& dataSeg)
514 {
515     dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
516     dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT;
517     dataSeg.status = TS_PARSE_STATUS_PARSED;
518 }
ParseHisyseventConfig(HtraceDataSegment & dataSeg)519 void HtraceParser::ParseHisyseventConfig(HtraceDataSegment& dataSeg)
520 {
521     dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
522     dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT_CONFIG;
523     dataSeg.status = TS_PARSE_STATUS_PARSED;
524 }
525 
ParseJSMemory(HtraceDataSegment & dataSeg)526 void HtraceParser::ParseJSMemory(HtraceDataSegment& dataSeg)
527 {
528     dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
529     dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY;
530     dataSeg.status = TS_PARSE_STATUS_PARSED;
531 }
532 
ParseJSMemoryConfig(HtraceDataSegment & dataSeg)533 void HtraceParser::ParseJSMemoryConfig(HtraceDataSegment& dataSeg)
534 {
535     dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
536     dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY_CONFIG;
537     dataSeg.status = TS_PARSE_STATUS_PARSED;
538 }
539 
GetNextSegment()540 int32_t HtraceParser::GetNextSegment()
541 {
542     int32_t head;
543     htraceDataSegMux_.lock();
544     head = parseHead_;
545     HtraceDataSegment& htraceDataSegmentSeg = dataSegArray_[head];
546     if (htraceDataSegmentSeg.status.load() != TS_PARSE_STATUS_SEPRATED) {
547         if (toExit_) {
548             parserThreadCount_--;
549             TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_);
550             TS_LOGD("seprateHead_x:\t%d, parseHead_:\t%d, filterHead_:\t%d status:%d\n", rawDataHead_, parseHead_,
551                     filterHead_, htraceDataSegmentSeg.status.load());
552             htraceDataSegMux_.unlock();
553             if (!parserThreadCount_ && !filterThreadStarted_) {
554                 exited_ = true;
555             }
556             return ERROR_CODE_EXIT;
557         }
558         if (htraceDataSegmentSeg.status.load() == TS_PARSE_STATUS_PARSING) {
559             htraceDataSegMux_.unlock();
560             usleep(sleepDur_);
561             return ERROR_CODE_NODATA;
562         }
563         htraceDataSegMux_.unlock();
564         usleep(sleepDur_);
565         return ERROR_CODE_NODATA;
566     }
567     parseHead_ = (parseHead_ + 1) % MAX_SEG_ARRAY_SIZE;
568     htraceDataSegmentSeg.status = TS_PARSE_STATUS_PARSING;
569     htraceDataSegMux_.unlock();
570     return head;
571 }
ParseDataRecursively(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)572 bool HtraceParser::ParseDataRecursively(std::deque<uint8_t>::iterator& packagesBegin, size_t& currentLength)
573 {
574     if (!hasGotHeader_) {
575         if (InitProfilerTraceFileHeader()) {
576             packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + PACKET_HEADER_LENGTH);
577             currentLength -= PACKET_HEADER_LENGTH;
578             packagesBegin += PACKET_HEADER_LENGTH;
579             htraceCurentLength_ = profilerTraceFileHeader_.data.length;
580             htraceCurentLength_ -= PACKET_HEADER_LENGTH;
581             hasGotHeader_ = true;
582             if (!currentLength) {
583                 return false;
584             }
585         } else {
586             TS_LOGE("get profiler trace file header failed");
587             return false;
588         }
589     }
590     if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) {
591         if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) {
592             auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH;
593             perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size);
594             currentLength -= size;
595             packagesBegin += size;
596             profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE;
597             hasGotHeader_ = false;
598             return true;
599         }
600         return false;
601     }
602     if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::STANDALONE_DATA) {
603         if (EBPF_PLUGIN_NAME.compare(profilerTraceFileHeader_.data.standalonePluginName) == 0 &&
604             packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) {
605             auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH;
606             ebpfDataParser_->InitAndParseEbpfData(packagesBuffer_, size);
607             currentLength -= size;
608             packagesBegin += size;
609             profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE;
610             hasGotHeader_ = false;
611             return true;
612         }
613 #if IS_WASM
614         if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) {
615             auto thirdPartySize = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH;
616             auto buffer = std::make_unique<uint8_t[]>(thirdPartySize).get();
617             std::copy(packagesBuffer_.begin(), packagesBuffer_.begin() + thirdPartySize, buffer);
618             TraceStreamer_Plugin_Out_Filter(reinterpret_cast<const char*>(buffer), thirdPartySize,
619                                             profilerTraceFileHeader_.data.standalonePluginName);
620             return true;
621         }
622 #endif
623         return false;
624     }
625     while (1) {
626         if (!hasGotSegLength_) {
627             if (currentLength < PACKET_SEG_LENGTH) {
628                 break;
629             }
630             std::string bufferLine(packagesBegin, packagesBegin + PACKET_SEG_LENGTH);
631             const uint32_t* len = reinterpret_cast<const uint32_t*>(bufferLine.data());
632             nextLength_ = *len;
633             htraceLength_ += nextLength_ + PACKET_SEG_LENGTH;
634             hasGotSegLength_ = true;
635             currentLength -= PACKET_SEG_LENGTH;
636             packagesBegin += PACKET_SEG_LENGTH;
637             htraceCurentLength_ -= PACKET_SEG_LENGTH;
638         }
639         if (currentLength < nextLength_) {
640             break;
641         }
642         std::string bufferLine(packagesBegin, packagesBegin + nextLength_);
643         ParseTraceDataItem(bufferLine);
644         hasGotSegLength_ = false;
645         packagesBegin += nextLength_;
646         currentLength -= nextLength_;
647         if (nextLength_ > htraceCurentLength_) {
648             TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%" PRIu64 "", nextLength_,
649                     htraceCurentLength_);
650         }
651         htraceCurentLength_ -= nextLength_;
652         if (htraceCurentLength_ == 0) {
653             hasGotHeader_ = false;
654             packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
655             profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE;
656             TS_LOGD("read proto finished!");
657             return ParseDataRecursively(packagesBegin, currentLength);
658         }
659     }
660     return true;
661 }
ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size)662 void HtraceParser::ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size)
663 {
664     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
665     auto packagesBegin = packagesBuffer_.begin();
666     auto currentLength = packagesBuffer_.size();
667     if (ParseDataRecursively(packagesBegin, currentLength)) {
668         packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
669     }
670     return;
671 }
StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size)672 void HtraceParser::StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size)
673 {
674     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
675     return;
676 }
TraceDataSegmentEnd()677 void HtraceParser::TraceDataSegmentEnd()
678 {
679     perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, packagesBuffer_.size());
680     packagesBuffer_.clear();
681     return;
682 }
683 
InitProfilerTraceFileHeader()684 bool HtraceParser::InitProfilerTraceFileHeader()
685 {
686     if (packagesBuffer_.size() < PACKET_HEADER_LENGTH) {
687         TS_LOGE("buffer size less than profiler trace file header");
688         return false;
689     }
690     uint8_t buffer[PACKET_HEADER_LENGTH];
691     (void)memset_s(buffer, PACKET_HEADER_LENGTH, 0, PACKET_HEADER_LENGTH);
692     int32_t i = 0;
693     for (auto it = packagesBuffer_.begin(); it != packagesBuffer_.begin() + PACKET_HEADER_LENGTH; ++it, ++i) {
694         buffer[i] = *it;
695     }
696     auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, PACKET_HEADER_LENGTH);
697     if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
698         TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %" PRIx64 "", ret,
699                 profilerTraceFileHeader_.data.magic);
700         return false;
701     }
702     if (profilerTraceFileHeader_.data.length <= PACKET_HEADER_LENGTH) {
703         TS_LOGE("Profiler Trace data is truncated!!!");
704         return false;
705     }
706     TS_LOGI("magic = %" PRIx64 ", length = %" PRIu64 ", dataType = %x, boottime = %" PRIu64 "",
707             profilerTraceFileHeader_.data.magic, profilerTraceFileHeader_.data.length,
708             profilerTraceFileHeader_.data.dataType, profilerTraceFileHeader_.data.boottime);
709 #if IS_WASM
710     const int32_t DATA_TYPE_CLOCK = 100;
711     TraceStreamer_Plugin_Out_SendData(reinterpret_cast<char*>(&profilerTraceFileHeader_),
712                                       sizeof(profilerTraceFileHeader_), DATA_TYPE_CLOCK);
713 #endif
714     htraceClockDetailParser_->Parse(&profilerTraceFileHeader_);
715     return true;
716 }
717 } // namespace TraceStreamer
718 } // namespace SysTuning
719