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