1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "native_hook_filter.h"
17 #include "native_hook_config.pbreader.h"
18 #include "ts_common.h"
19 #include <cstddef>
20 #include <cinttypes>
21 namespace SysTuning {
22 namespace TraceStreamer {
NativeHookFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)23 NativeHookFilter::NativeHookFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
24 : OfflineSymbolizationFilter(dataCache, filter),
25 anonMmapData_(nullptr),
26 hookPluginData_(std::make_unique<ProfilerPluginData>()),
27 ipidToSymIdToSymIndex_(INVALID_UINT64),
28 ipidToFilePathIdToFileIndex_(INVALID_UINT64),
29 ipidToFrameIdToFrameBytes_(nullptr)
30 {
31 invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib/libc++.so"));
32 invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib64/libc++.so"));
33 invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib/ld-musl-aarch64.so.1"));
34 invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib/ld-musl-arm.so.1"));
35 hookPluginData_->set_name("nativehook");
36 commHookData_.datas = std::make_unique<BatchNativeHookData>();
37 addrToAllocEventRow_ = traceDataCache_->GetNativeHookData()->GetAddrToAllocEventRow();
38 addrToMmapEventRow_ = traceDataCache_->GetNativeHookData()->GetAddrToMmapEventRow();
39 }
40
ParseConfigInfo(ProtoReader::BytesView & protoData,uint64_t & statisticsInterval)41 void NativeHookFilter::ParseConfigInfo(ProtoReader::BytesView &protoData, uint64_t &statisticsInterval)
42 {
43 auto configReader = ProtoReader::NativeHookConfig_Reader(protoData);
44 if (configReader.has_expand_pids() || (configReader.has_process_name() && configReader.has_pid())) {
45 isSingleProcData_ = false;
46 }
47 if (configReader.has_statistics_interval()) {
48 isStatisticMode_ = true;
49 isCallStackCompressedMode_ = true;
50 isStringCompressedMode_ = true;
51 statisticsInterval = configReader.statistics_interval() * SEC_TO_NS;
52 }
53 if (configReader.has_response_library_mode() || configReader.has_offline_symbolization()) {
54 isOfflineSymbolizationMode_ = true;
55 isCallStackCompressedMode_ = true;
56 isStringCompressedMode_ = true;
57 return;
58 }
59 if (configReader.has_callframe_compress()) {
60 isCallStackCompressedMode_ = true;
61 isStringCompressedMode_ = true;
62 return;
63 }
64 if (configReader.has_string_compressed()) {
65 isStringCompressedMode_ = true;
66 return;
67 }
68 return;
69 }
AppendStackMaps(uint32_t ipid,uint32_t stackid,std::vector<uint64_t> & frames)70 void NativeHookFilter::AppendStackMaps(uint32_t ipid, uint32_t stackid, std::vector<uint64_t> &frames)
71 {
72 uint64_t ipidWithStackIdIndex = 0;
73 // the last element is ipid for this batch of frames/ips
74 if (isSingleProcData_) {
75 frames.emplace_back(SINGLE_PROC_IPID);
76 ipidWithStackIdIndex = stackid;
77 } else {
78 frames.emplace_back(ipid);
79 ipidWithStackIdIndex = traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(stackid));
80 }
81 auto framesSharedPtr = std::make_shared<std::vector<uint64_t>>(frames);
82 stackIdToFramesMap_.emplace(std::make_pair(ipidWithStackIdIndex, framesSharedPtr));
83 // allStackIdToFramesMap_ save all offline symbolic call stack
84 if (isOfflineSymbolizationMode_) {
85 allStackIdToFramesMap_.emplace(std::make_pair(ipidWithStackIdIndex, framesSharedPtr));
86 }
87 }
AppendFrameMaps(uint32_t ipid,uint32_t frameMapId,const ProtoReader::BytesView & bytesView)88 void NativeHookFilter::AppendFrameMaps(uint32_t ipid, uint32_t frameMapId, const ProtoReader::BytesView &bytesView)
89 {
90 auto frames = std::make_shared<const ProtoReader::BytesView>(bytesView);
91 if (isSingleProcData_) {
92 ipidToFrameIdToFrameBytes_.Insert(SINGLE_PROC_IPID, frameMapId, frames);
93 } else {
94 ipidToFrameIdToFrameBytes_.Insert(ipid, frameMapId, frames);
95 }
96 }
AppendFilePathMaps(uint32_t ipid,uint32_t filePathId,uint64_t fileIndex)97 void NativeHookFilter::AppendFilePathMaps(uint32_t ipid, uint32_t filePathId, uint64_t fileIndex)
98 {
99 if (isSingleProcData_) {
100 ipidToFilePathIdToFileIndex_.Insert(SINGLE_PROC_IPID, filePathId, fileIndex);
101 } else {
102 ipidToFilePathIdToFileIndex_.Insert(ipid, filePathId, fileIndex);
103 }
104 }
AppendSymbolMap(uint32_t ipid,uint32_t symId,uint64_t symbolIndex)105 void NativeHookFilter::AppendSymbolMap(uint32_t ipid, uint32_t symId, uint64_t symbolIndex)
106 {
107 if (isSingleProcData_) {
108 ipidToSymIdToSymIndex_.Insert(SINGLE_PROC_IPID, symId, symbolIndex);
109 } else {
110 ipidToSymIdToSymIndex_.Insert(ipid, symId, symbolIndex);
111 }
112 }
AppendThreadNameMap(uint32_t ipid,uint32_t nameId,uint64_t threadNameIndex)113 void NativeHookFilter::AppendThreadNameMap(uint32_t ipid, uint32_t nameId, uint64_t threadNameIndex)
114 {
115 uint64_t ipidWithThreadNameIdIndex = 0;
116 if (isSingleProcData_) {
117 ipidWithThreadNameIdIndex = nameId;
118 } else {
119 ipidWithThreadNameIdIndex = traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(nameId));
120 }
121 threadNameIdToThreadNameIndex_.emplace(ipidWithThreadNameIdIndex, threadNameIndex);
122 }
123
124 template <class T1, class T2>
UpdateMap(std::unordered_map<T1,T2> & sourceMap,T1 key,T2 value)125 void NativeHookFilter::UpdateMap(std::unordered_map<T1, T2> &sourceMap, T1 key, T2 value)
126 {
127 auto itor = sourceMap.find(key);
128 if (itor != sourceMap.end()) {
129 itor->second = value;
130 } else {
131 sourceMap.insert(std::make_pair(key, value));
132 }
133 }
ParseFrame(uint64_t row,const ProtoReader::DataArea & frame)134 std::unique_ptr<NativeHookFrameInfo> NativeHookFilter::ParseFrame(uint64_t row, const ProtoReader::DataArea &frame)
135 {
136 auto frameInfo = std::make_unique<NativeHookFrameInfo>();
137
138 ProtoReader::Frame_Reader reader(frame.Data(), frame.Size());
139 auto curCacheIpid = traceDataCache_->GetNativeHookData()->Ipids()[row];
140 if (isSingleProcData_) {
141 curCacheIpid = SINGLE_PROC_IPID;
142 }
143 if (isStringCompressedMode_) {
144 frameInfo->symbolIndex_ = ipidToSymIdToSymIndex_.Find(curCacheIpid, reader.symbol_name_id());
145 TS_CHECK_TRUE(frameInfo->symbolIndex_ != INVALID_UINT64, nullptr,
146 "Native hook ParseFrame find symbol id failed!!!");
147 frameInfo->filePathIndex_ = ipidToFilePathIdToFileIndex_.Find(curCacheIpid, reader.file_path_id());
148 TS_CHECK_TRUE(frameInfo->filePathIndex_ != INVALID_UINT64, nullptr,
149 "Native hook ParseFrame find file path id failed!!!");
150 } else {
151 frameInfo->symbolIndex_ = traceDataCache_->dataDict_.GetStringIndex(reader.symbol_name().ToStdString());
152 frameInfo->filePathIndex_ = traceDataCache_->dataDict_.GetStringIndex(reader.file_path().ToStdString());
153 }
154 // 0 is meaningful, but it is not displayed. Other data is still needed
155 if (reader.has_ip()) {
156 frameInfo->ip_ = reader.ip();
157 }
158 if (reader.has_offset()) {
159 frameInfo->offset_ = reader.offset();
160 }
161 if (reader.has_symbol_offset()) {
162 frameInfo->symbolOffset_ = reader.symbol_offset();
163 }
164 return frameInfo;
165 }
166
CompressStackAndFrames(uint64_t row,ProtoReader::RepeatedDataAreaIterator<ProtoReader::BytesView> frames)167 void NativeHookFilter::CompressStackAndFrames(uint64_t row,
168 ProtoReader::RepeatedDataAreaIterator<ProtoReader::BytesView> frames)
169 {
170 std::vector<uint64_t> framesHash;
171 std::string framesHashStr = "";
172 for (auto itor = frames; itor; itor++) {
173 std::string_view frameStr(reinterpret_cast<const char *>(itor->Data()), itor->Size());
174 auto frameHash = hashFun_(frameStr);
175 if (!frameHashToFrameInfoMap_.count(frameHash)) {
176 // the frame compression is completed and the frame is parsed.
177 auto frameInfo = ParseFrame(row, itor.GetDataArea());
178 if (!frameInfo) {
179 continue;
180 }
181 frameHashToFrameInfoMap_.emplace(std::make_pair(frameHash, std::move(frameInfo)));
182 }
183 framesHash.emplace_back(frameHash);
184 framesHashStr.append("+");
185 framesHashStr.append(std::to_string(frameHash));
186 }
187 auto stackHashValue = hashFun_(framesHashStr);
188 uint32_t callChainId = INVALID_UINT32;
189 if (!stackHashValueToCallChainIdMap_.count(stackHashValue)) {
190 callChainId = callChainIdToStackHashValueMap_.size() + 1;
191 callChainIdToStackHashValueMap_.emplace(std::make_pair(callChainId, stackHashValue));
192 stackHashValueToCallChainIdMap_.emplace(std::make_pair(stackHashValue, callChainId));
193 stackHashValueToFramesHashMap_.emplace(std::make_pair(stackHashValue, std::move(framesHash)));
194 } else {
195 callChainId = stackHashValueToCallChainIdMap_[stackHashValue];
196 }
197 // When compressing the call stack, update the callChainId of the nativeHook table
198 traceDataCache_->GetNativeHookData()->UpdateCallChainId(row, callChainId);
199 }
ParseStatisticEvent(uint64_t timeStamp,const ProtoReader::BytesView & bytesView)200 void NativeHookFilter::ParseStatisticEvent(uint64_t timeStamp, const ProtoReader::BytesView &bytesView)
201 {
202 ProtoReader::RecordStatisticsEvent_Reader reader(bytesView);
203 uint32_t callChainId = INVALID_UINT32;
204 uint64_t ipidWithCallChainIdIndex = INVALID_UINT64;
205 auto ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp, reader.pid());
206 if (isSingleProcData_) {
207 ipidWithCallChainIdIndex = reader.callstack_id();
208 } else {
209 ipidWithCallChainIdIndex =
210 traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(reader.callstack_id()));
211 }
212 // When the stack id is zero, there is no matching call stack
213 if (isOfflineSymbolizationMode_ && reader.callstack_id()) {
214 // The same call stack may have different symbolic results due to changes in the symbol table
215 if (stackIdToCallChainIdMap_.count(ipidWithCallChainIdIndex)) {
216 callChainId = stackIdToCallChainIdMap_.at(ipidWithCallChainIdIndex);
217 } else {
218 TS_LOGE("invalid callChainId, can not find stack id : %u in stackIdToCallChainIdMap_!",
219 reader.callstack_id());
220 }
221 } else if (reader.callstack_id()) { // when isStatisticMode_ is true, isCallStackCompressedMode_ must be true.
222 // when isOfflineSymblolizationMode_ is false, the stack id is unique
223 callChainId = ipidWithCallChainIdIndex;
224 }
225 #if !defined(IS_WASM)
226 // 统计模式数据冗余优化在wasm下关闭
227 if (reader.apply_size() == reader.release_size() && callChainIdsSet_.find(callChainId) == callChainIdsSet_.end()) {
228 return;
229 } else {
230 callChainIdsSet_.emplace(callChainId);
231 }
232 #endif
233 DataIndex memSubType = INVALID_UINT64;
234 if (reader.has_tag_name()) {
235 memSubType = traceDataCache_->GetDataIndex(reader.tag_name().ToStdString());
236 }
237 NativeHookStatisticRow nativeHookStatisticRow = {ipid,
238 timeStamp,
239 callChainId,
240 static_cast<uint32_t>(reader.type()),
241 memSubType,
242 reader.apply_count(),
243 reader.release_count(),
244 reader.apply_size(),
245 reader.release_size()};
246 traceDataCache_->GetNativeHookStatisticsData()->AppendNewNativeHookStatistic(nativeHookStatisticRow);
247 }
ParseAllocEvent(uint64_t timeStamp,const ProtoReader::BytesView & bytesView)248 void NativeHookFilter::ParseAllocEvent(uint64_t timeStamp, const ProtoReader::BytesView &bytesView)
249 {
250 ProtoReader::AllocEvent_Reader allocEventReader(bytesView);
251 uint32_t callChainId = INVALID_UINT32;
252 auto itid =
253 streamFilters_->processFilter_->GetOrCreateThreadWithPid(allocEventReader.tid(), allocEventReader.pid());
254 auto ipid = traceDataCache_->GetConstThreadData(itid).internalPid_;
255 uint64_t ipidWithStackIdIndex = INVALID_UINT64;
256 uint64_t ipidWithThreadNameIdIndex = INVALID_UINT64;
257 if (isSingleProcData_) {
258 ipidWithThreadNameIdIndex = allocEventReader.thread_name_id();
259 ipidWithStackIdIndex = allocEventReader.stack_id();
260 } else {
261 ipidWithThreadNameIdIndex = traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" +
262 std::to_string(allocEventReader.thread_name_id()));
263 ipidWithStackIdIndex =
264 traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(allocEventReader.stack_id()));
265 }
266 // When the stack id is zero, there is no matching call stack
267 if (isOfflineSymbolizationMode_ && allocEventReader.stack_id()) {
268 // The same call stack may have different symbolic results due to changes in the symbol table
269 if (stackIdToCallChainIdMap_.count(ipidWithStackIdIndex)) {
270 callChainId = stackIdToCallChainIdMap_.at(ipidWithStackIdIndex);
271 } else {
272 TS_LOGE("invalid callChainId, can not find pid with stack id : %" PRIu64 " in stackIdToCallChainIdMap_!",
273 ipidWithStackIdIndex);
274 }
275 } else if (isCallStackCompressedMode_ && allocEventReader.stack_id()) {
276 // when isOfflineSymblolizationMode_ is false && isCallStackCompressedMode is true, the stack id is unique
277 callChainId = ipidWithStackIdIndex;
278 }
279
280 if (allocEventReader.has_thread_name_id()) {
281 UpdateMap(itidToThreadNameId_, itid, ipidWithThreadNameIdIndex);
282 }
283 NativeHookRow nativeHookRow = {callChainId,
284 ipid,
285 itid,
286 "AllocEvent",
287 INVALID_UINT64,
288 timeStamp,
289 0,
290 0,
291 allocEventReader.addr(),
292 static_cast<int64_t>(allocEventReader.size())};
293 auto row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData(nativeHookRow);
294 addrToAllocEventRow_->insert(std::make_pair(allocEventReader.addr(), static_cast<uint64_t>(row)));
295 if (allocEventReader.size() != 0) {
296 MaybeUpdateCurrentSizeDur(row, timeStamp, true);
297 }
298 // Uncompressed call stack
299 if (allocEventReader.has_frame_info()) {
300 CompressStackAndFrames(row, allocEventReader.frame_info());
301 }
302 }
303
SetFreeEventCallChainId(uint32_t & callChainId,uint32_t ipid,uint32_t itid,const ProtoReader::FreeEvent_Reader & freeEventReader)304 void NativeHookFilter::SetFreeEventCallChainId(uint32_t &callChainId,
305 uint32_t ipid,
306 uint32_t itid,
307 const ProtoReader::FreeEvent_Reader &freeEventReader)
308 {
309 uint64_t ipidWithStackIdIndex = INVALID_UINT64;
310 uint64_t ipidWithThreadNameIdIndex = INVALID_UINT64;
311 if (isSingleProcData_) {
312 ipidWithStackIdIndex = freeEventReader.stack_id();
313 ipidWithThreadNameIdIndex = freeEventReader.thread_name_id();
314 } else {
315 ipidWithThreadNameIdIndex = traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" +
316 std::to_string(freeEventReader.thread_name_id()));
317 ipidWithStackIdIndex =
318 traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(freeEventReader.stack_id()));
319 }
320 // When the stack id is zero, there is no matching call stack
321 if (isOfflineSymbolizationMode_ && freeEventReader.stack_id()) {
322 // The same call stack may have different symbolic results due to changes in the symbol table
323 if (stackIdToCallChainIdMap_.count(ipidWithStackIdIndex)) {
324 callChainId = stackIdToCallChainIdMap_.at(ipidWithStackIdIndex);
325 } else {
326 TS_LOGE("invalid callChainId, can not find pid with stack id : %" PRIu64 " in stackIdToCallChainIdMap_!",
327 ipidWithStackIdIndex);
328 }
329 } else if (isCallStackCompressedMode_ && freeEventReader.stack_id()) {
330 // when isOfflineSymblolizationMode_ is false && isCallStackCompressedMode is true, the stack id is unique
331 callChainId = ipidWithStackIdIndex;
332 }
333 if (freeEventReader.thread_name_id() != 0) {
334 UpdateMap(itidToThreadNameId_, itid, ipidWithThreadNameIdIndex);
335 }
336 }
ParseFreeEvent(uint64_t timeStamp,const ProtoReader::BytesView & bytesView)337 void NativeHookFilter::ParseFreeEvent(uint64_t timeStamp, const ProtoReader::BytesView &bytesView)
338 {
339 ProtoReader::FreeEvent_Reader freeEventReader(bytesView);
340 uint32_t callChainId = INVALID_UINT32;
341 auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(freeEventReader.tid(), freeEventReader.pid());
342 auto ipid = traceDataCache_->GetConstThreadData(itid).internalPid_;
343 SetFreeEventCallChainId(callChainId, ipid, itid, freeEventReader);
344 int64_t freeHeapSize = 0;
345 // Find a matching malloc event, and if the matching fails, do not write to the database
346 uint64_t row = INVALID_UINT64;
347 if (addrToAllocEventRow_->count(freeEventReader.addr())) {
348 row = addrToAllocEventRow_->at(freeEventReader.addr());
349 }
350 if (row != INVALID_UINT64 && timeStamp > traceDataCache_->GetNativeHookData()->TimeStampData()[row]) {
351 addrToAllocEventRow_->erase(freeEventReader.addr());
352 traceDataCache_->GetNativeHookData()->UpdateEndTimeStampAndDuration(row, timeStamp);
353 freeHeapSize = traceDataCache_->GetNativeHookData()->MemSizes()[row];
354 } else {
355 TS_LOGD("func addr:%" PRIu64 " is empty", freeEventReader.addr());
356 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID);
357 return;
358 }
359 NativeHookRow nativeHookRow = {
360 callChainId, ipid, itid, "FreeEvent", INVALID_UINT64, timeStamp, 0, 0, freeEventReader.addr(), freeHeapSize};
361 row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData(nativeHookRow);
362 if (freeHeapSize != 0) {
363 MaybeUpdateCurrentSizeDur(row, timeStamp, true);
364 }
365 // Uncompressed call stack
366 if (freeEventReader.has_frame_info()) {
367 CompressStackAndFrames(row, freeEventReader.frame_info());
368 }
369 }
SetMmapEventCallChainId(uint32_t & callChainId,uint32_t ipid,uint32_t itid,const ProtoReader::MmapEvent_Reader & mMapEventReader)370 void NativeHookFilter::SetMmapEventCallChainId(uint32_t &callChainId,
371 uint32_t ipid,
372 uint32_t itid,
373 const ProtoReader::MmapEvent_Reader &mMapEventReader)
374 {
375 uint64_t ipidWithStackIdIndex = INVALID_UINT64;
376 uint64_t ipidWithThreadNameIdIndex = INVALID_UINT64;
377 if (isSingleProcData_) {
378 ipidWithStackIdIndex = mMapEventReader.stack_id();
379 ipidWithThreadNameIdIndex = mMapEventReader.thread_name_id();
380 } else {
381 ipidWithThreadNameIdIndex = traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" +
382 std::to_string(mMapEventReader.thread_name_id()));
383 ipidWithStackIdIndex =
384 traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(mMapEventReader.stack_id()));
385 }
386 // When the stack id is zero, there is no matching call stack
387 if (isOfflineSymbolizationMode_ && mMapEventReader.stack_id()) {
388 // The same call stack may have different symbolic results due to changes in the symbol table
389 if (stackIdToCallChainIdMap_.count(ipidWithStackIdIndex)) {
390 callChainId = stackIdToCallChainIdMap_.at(ipidWithStackIdIndex);
391 } else {
392 TS_LOGE("invalid callChainId, can not find pid with stack id : %" PRIu64 " in stackIdToCallChainIdMap_!",
393 ipidWithStackIdIndex);
394 }
395 } else if (isCallStackCompressedMode_ && mMapEventReader.stack_id()) {
396 // when isOfflineSymblolizationMode_ is false && isCallStackCompressedMode is true, the stack id is unique
397 callChainId = ipidWithStackIdIndex;
398 }
399 // Update the mapping of tid to thread name id.
400 if (mMapEventReader.thread_name_id() != 0) {
401 UpdateMap(itidToThreadNameId_, itid, ipidWithThreadNameIdIndex);
402 }
403 }
ParseMmapEvent(uint64_t timeStamp,const ProtoReader::BytesView & bytesView)404 void NativeHookFilter::ParseMmapEvent(uint64_t timeStamp, const ProtoReader::BytesView &bytesView)
405 {
406 ProtoReader::MmapEvent_Reader mMapEventReader(bytesView);
407 uint32_t callChainId = INVALID_UINT32;
408 auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(mMapEventReader.tid(), mMapEventReader.pid());
409 auto ipid = traceDataCache_->GetConstThreadData(itid).internalPid_;
410 SetMmapEventCallChainId(callChainId, ipid, itid, mMapEventReader);
411 // Gets the index of the mmap event's label in the data dictionary
412 DataIndex subType = INVALID_UINT64;
413 auto mMapAddr = mMapEventReader.addr();
414 auto mMapSize = mMapEventReader.size();
415 if (mMapEventReader.has_type() && !mMapEventReader.type().ToStdString().empty()) {
416 subType = traceDataCache_->dataDict_.GetStringIndex(mMapEventReader.type().ToStdString());
417 // Establish a mapping of addr and size to the mmap tag index.
418 addrToMmapTag_[mMapAddr] = subType; // update addr to MemMapSubType
419 }
420 NativeHookRow nativeHookRow = {callChainId, ipid, itid, "MmapEvent", subType,
421 timeStamp, 0, 0, mMapAddr, static_cast<int64_t>(mMapSize)};
422 auto row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData(nativeHookRow);
423 if (subType == INVALID_UINT64) {
424 UpdateAnonMmapDataDbIndex(mMapAddr, mMapSize, static_cast<uint64_t>(row));
425 }
426 addrToMmapEventRow_->insert(std::make_pair(mMapAddr, static_cast<uint64_t>(row)));
427 // update currentSizeDur.
428 if (mMapSize) {
429 MaybeUpdateCurrentSizeDur(row, timeStamp, false);
430 }
431 // Uncompressed call stack
432 if (mMapEventReader.has_frame_info()) {
433 CompressStackAndFrames(row, mMapEventReader.frame_info());
434 }
435 }
SetMunmapEventCallChainId(uint32_t & callChainId,uint32_t ipid,uint32_t itid,const ProtoReader::MunmapEvent_Reader & mUnmapEventReader)436 void NativeHookFilter::SetMunmapEventCallChainId(uint32_t &callChainId,
437 uint32_t ipid,
438 uint32_t itid,
439 const ProtoReader::MunmapEvent_Reader &mUnmapEventReader)
440 {
441 uint64_t ipidWithStackIdIndex = INVALID_UINT64;
442 uint64_t ipidWithThreadNameIdIndex = INVALID_UINT64;
443 if (isSingleProcData_) {
444 ipidWithStackIdIndex = mUnmapEventReader.stack_id();
445 ipidWithThreadNameIdIndex = mUnmapEventReader.thread_name_id();
446 } else {
447 ipidWithThreadNameIdIndex = traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" +
448 std::to_string(mUnmapEventReader.thread_name_id()));
449 ipidWithStackIdIndex =
450 traceDataCache_->GetDataIndex(std::to_string(ipid) + "_" + std::to_string(mUnmapEventReader.stack_id()));
451 }
452 // When the stack id is zero, there is no matching call stack
453 if (isOfflineSymbolizationMode_) {
454 // The same call stack may have different symbolic results due to changes in the symbol table
455 if (stackIdToCallChainIdMap_.count(ipidWithStackIdIndex)) {
456 callChainId = stackIdToCallChainIdMap_.at(mUnmapEventReader.stack_id());
457 } else {
458 TS_LOGE("invalid callChainId, can not find pid with stack id : %" PRIu64 " in stackIdToCallChainIdMap_!",
459 ipidWithStackIdIndex);
460 }
461 } else if (isCallStackCompressedMode_) {
462 // when isOfflineSymblolizationMode_ is false && isCallStackCompressedMode is true, the stack id is unique
463 callChainId = ipidWithStackIdIndex;
464 }
465 if (mUnmapEventReader.thread_name_id() != 0) {
466 UpdateMap(itidToThreadNameId_, itid, ipidWithThreadNameIdIndex);
467 }
468 }
ParseMunmapEvent(uint64_t timeStamp,const ProtoReader::BytesView & bytesView)469 void NativeHookFilter::ParseMunmapEvent(uint64_t timeStamp, const ProtoReader::BytesView &bytesView)
470 {
471 ProtoReader::MunmapEvent_Reader mUnmapEventReader(bytesView);
472 uint32_t callChainId = INVALID_UINT32;
473 auto itid =
474 streamFilters_->processFilter_->GetOrCreateThreadWithPid(mUnmapEventReader.tid(), mUnmapEventReader.pid());
475 auto ipid = traceDataCache_->GetConstThreadData(itid).internalPid_;
476 SetMunmapEventCallChainId(callChainId, ipid, itid, mUnmapEventReader);
477 // Query for MMAP events that match the current data. If there are no matching MMAP events, the current data is not
478 // written to the database.
479 uint64_t row = INVALID_UINT64;
480 if (addrToMmapEventRow_->count(mUnmapEventReader.addr())) {
481 row = addrToMmapEventRow_->at(mUnmapEventReader.addr());
482 }
483 if (row != INVALID_UINT64 && timeStamp > traceDataCache_->GetNativeHookData()->TimeStampData()[row]) {
484 addrToMmapEventRow_->erase(mUnmapEventReader.addr());
485 traceDataCache_->GetNativeHookData()->UpdateEndTimeStampAndDuration(row, timeStamp);
486 } else {
487 TS_LOGD("func addr:%" PRIu64 " is empty", mUnmapEventReader.addr());
488 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_DATA_INVALID);
489 return;
490 }
491 NativeHookRow nativeHookRow = {callChainId,
492 ipid,
493 itid,
494 "MunmapEvent",
495 GetMemMapSubTypeWithAddr(mUnmapEventReader.addr()),
496 timeStamp,
497 0,
498 0,
499 mUnmapEventReader.addr(),
500 static_cast<int64_t>(mUnmapEventReader.size())};
501 row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData(nativeHookRow);
502 addrToMmapTag_.erase(mUnmapEventReader.addr()); // earse MemMapSubType with addr
503 if (mUnmapEventReader.size() != 0) {
504 MaybeUpdateCurrentSizeDur(row, timeStamp, false);
505 }
506 // Uncompressed call stack
507 if (mUnmapEventReader.has_frame_info()) {
508 CompressStackAndFrames(row, mUnmapEventReader.frame_info());
509 }
510 }
ParseTagEvent(const ProtoReader::BytesView & bytesView)511 void NativeHookFilter::ParseTagEvent(const ProtoReader::BytesView &bytesView)
512 {
513 ProtoReader::MemTagEvent_Reader memTagEventReader(bytesView);
514 auto addr = memTagEventReader.addr();
515 auto size = memTagEventReader.size();
516 if (traceDataCache_->isSplitFile_) {
517 auto hookData = commHookData_.datas->add_events();
518 MemTagEvent *memTagEvent = hookData->mutable_tag_event();
519 memTagEvent->ParseFromArray(bytesView.Data(), bytesView.Size());
520 commHookData_.size += bytesView.Size();
521 return;
522 }
523 auto tagIndex = traceDataCache_->dataDict_.GetStringIndex(memTagEventReader.tag().ToStdString());
524 NativeHook *nativeHookPtr = traceDataCache_->GetNativeHookData();
525 std::shared_ptr<std::set<uint64_t>> indexSetPtr = anonMmapData_.Find(addr, size); // get anonMmapData dbIndex
526 if (indexSetPtr != nullptr) {
527 for (auto rowIter = indexSetPtr->begin(); rowIter != indexSetPtr->end(); rowIter++) {
528 nativeHookPtr->UpdateMemMapSubType(*rowIter, tagIndex);
529 }
530 indexSetPtr->clear(); // clear annoMmapData dbIndex
531 addrToMmapTag_[addr] = tagIndex; // update addr to MemMapSubType
532 }
533 }
GetMemMapSubTypeWithAddr(uint64_t addr)534 inline uint64_t NativeHookFilter::GetMemMapSubTypeWithAddr(uint64_t addr)
535 {
536 auto iter = addrToMmapTag_.find(addr);
537 if (iter != addrToMmapTag_.end()) {
538 return iter->second; // subType
539 } else {
540 return INVALID_UINT64;
541 }
542 }
UpdateAnonMmapDataDbIndex(uint64_t addr,uint64_t size,uint64_t row)543 inline void NativeHookFilter::UpdateAnonMmapDataDbIndex(uint64_t addr, uint64_t size, uint64_t row)
544 {
545 auto indexPtr = anonMmapData_.Find(addr, size);
546 if (indexPtr == nullptr) {
547 std::shared_ptr<std::set<uint64_t>> rowPtr_ = std::make_shared<std::set<uint64_t>>();
548 rowPtr_->insert(row);
549 anonMmapData_.Insert(addr, size, std::move(rowPtr_));
550 } else {
551 indexPtr->insert(row);
552 }
553 }
FilterNativeHookMainEvent(size_t num)554 void NativeHookFilter::FilterNativeHookMainEvent(size_t num)
555 {
556 auto itor = tsToMainEventsMap_.begin();
557 for (; itor != tsToMainEventsMap_.end() && num; num--, itor++) {
558 auto nativeHookDataReader = itor->second->reader_.get();
559 auto timeStamp = itor->first;
560 if (nativeHookDataReader->has_alloc_event()) {
561 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED);
562 ParseAllocEvent(timeStamp, nativeHookDataReader->alloc_event());
563 } else if (nativeHookDataReader->has_free_event()) {
564 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED);
565 ParseFreeEvent(timeStamp, nativeHookDataReader->free_event());
566 } else if (nativeHookDataReader->has_mmap_event()) {
567 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED);
568 ParseMmapEvent(timeStamp, nativeHookDataReader->mmap_event());
569 } else if (nativeHookDataReader->has_munmap_event()) {
570 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED);
571 ParseMunmapEvent(timeStamp, nativeHookDataReader->munmap_event());
572 } else if (nativeHookDataReader->has_statistics_event()) {
573 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_RECORD_STATISTICS, STAT_EVENT_RECEIVED);
574 ParseStatisticEvent(timeStamp, nativeHookDataReader->statistics_event());
575 } else if (nativeHookDataReader->has_tag_event()) {
576 streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MEMTAG, STAT_EVENT_RECEIVED);
577 ParseTagEvent(nativeHookDataReader->tag_event());
578 }
579 }
580 tsToMainEventsMap_.erase(tsToMainEventsMap_.begin(), itor);
581 }
582
MaybeParseNativeHookMainEvent(uint64_t timeStamp,std::unique_ptr<NativeHookMetaData> nativeHookMetaData)583 void NativeHookFilter::MaybeParseNativeHookMainEvent(uint64_t timeStamp,
584 std::unique_ptr<NativeHookMetaData> nativeHookMetaData)
585 {
586 tsToMainEventsMap_.insert(std::make_pair(timeStamp, std::move(nativeHookMetaData)));
587 if (tsToMainEventsMap_.size() > MAX_CACHE_SIZE) {
588 if (isOfflineSymbolizationMode_) {
589 ParseFramesInOfflineSymbolizationMode();
590 ReparseStacksWithDifferentMeans();
591 }
592 FilterNativeHookMainEvent(tsToMainEventsMap_.size() - MAX_CACHE_SIZE);
593 }
594 }
595
596 // Returns the address range of memMaps that conflict with start Addr and endAddr, as [start, end).
GetNeedUpdateProcessMapsAddrRange(uint32_t ipid,uint64_t startAddr,uint64_t endAddr)597 std::tuple<uint64_t, uint64_t> NativeHookFilter::GetNeedUpdateProcessMapsAddrRange(uint32_t ipid,
598 uint64_t startAddr,
599 uint64_t endAddr)
600 {
601 uint64_t start = INVALID_UINT64;
602 uint64_t end = INVALID_UINT64;
603 auto startAddrToMapsInfoMapPtr = ipidToStartAddrToMapsInfoMap_.Find(ipid);
604 if (startAddr >= endAddr || startAddrToMapsInfoMapPtr == nullptr) {
605 return std::make_tuple(start, end);
606 }
607 // Find first item in startAddrToMapsInfoMapPtr,
608 // that startItor->second()->start <= startAddr && startItor->second()->end > startAddr.
609 auto startItor = startAddrToMapsInfoMapPtr->upper_bound(startAddr);
610 if (startAddrToMapsInfoMapPtr->begin() != startItor) {
611 --startItor;
612 // Follow the rules of front closing and rear opening, [start, end)
613 if (startItor != startAddrToMapsInfoMapPtr->end() && startAddr >= startItor->second->end()) {
614 ++startItor;
615 }
616 }
617 // Forward query for the last item with filePathId == startItor ->filePathId()
618 if (startItor != startAddrToMapsInfoMapPtr->end()) {
619 auto startFilePathId = startItor->second->file_path_id();
620 while (startAddrToMapsInfoMapPtr->begin() != startItor) {
621 --startItor;
622 if (startFilePathId != startItor->second->file_path_id()) {
623 ++startItor;
624 break;
625 }
626 }
627 start = startItor->first;
628 }
629
630 // Find first item in startAddrToMapsInfoMapPtr, that endItor->second()->start > endAddr
631 auto endItor = startAddrToMapsInfoMapPtr->upper_bound(endAddr);
632 if (endItor == startAddrToMapsInfoMapPtr->end()) {
633 return std::make_tuple(start, end);
634 }
635 if (endItor == startAddrToMapsInfoMapPtr->begin()) {
636 start = INVALID_UINT64;
637 return std::make_tuple(start, end);
638 }
639 // Backward query for the last item with filePathId == endItor ->filePathId()
640 --endItor;
641 auto endFilePathId = endItor->second->file_path_id();
642 ++endItor;
643 while (endItor != startAddrToMapsInfoMapPtr->end()) {
644 if (endFilePathId != endItor->second->file_path_id()) {
645 end = endItor->second->start();
646 break;
647 }
648 endItor++;
649 }
650 return std::make_tuple(start, end);
651 }
652
ParseArktsOfflineSymbolization(uint64_t ipid,uint64_t arktsIp)653 std::shared_ptr<FrameInfo> NativeHookFilter::ParseArktsOfflineSymbolization(uint64_t ipid, uint64_t arktsIp)
654 {
655 auto arktsFrameInfo = std::make_shared<FrameInfo>();
656 // Under offline symbolization, there is no need to symbolize js data
657 uint64_t arktsFrame = arktsIp & (~JS_IP_MASK);
658 auto arktsReaderFrameInfo = ipidToFrameIdToFrameBytes_.Find(ipid, arktsFrame);
659 if (arktsReaderFrameInfo == nullptr) {
660 TS_LOGE("Can not to find Frame_map.id for js(arkts)!!!");
661 return nullptr;
662 }
663 ProtoReader::Frame_Reader reader(*arktsReaderFrameInfo);
664 // 0 is meaningful, but it is not displayed. Other data is still needed
665 // For js, the last 5 bytes of stack.ip and the outgoing frame member IP are reserved
666 if (reader.has_ip()) {
667 arktsFrameInfo->ip_ = reader.ip();
668 }
669 if (reader.has_symbol_name_id()) {
670 arktsFrameInfo->symbolIndex_ = ipidToSymIdToSymIndex_.Find(ipid, reader.symbol_name_id());
671 }
672 if (reader.has_file_path_id()) {
673 arktsFrameInfo->filePathId_ = reader.file_path_id();
674 }
675 if (reader.has_offset()) {
676 arktsFrameInfo->offset_ = reader.offset();
677 }
678 // Unchanged data is the default value
679 return arktsFrameInfo;
680 }
681
OfflineSymbolization(const std::shared_ptr<std::vector<uint64_t>> ips)682 std::shared_ptr<std::vector<std::shared_ptr<FrameInfo>>> NativeHookFilter::OfflineSymbolization(
683 const std::shared_ptr<std::vector<uint64_t>> ips)
684 {
685 auto ipid = ips->back();
686 auto result = std::make_shared<std::vector<std::shared_ptr<FrameInfo>>>();
687 for (auto itor = ips->begin(); (itor + 1) != ips->end(); itor++) {
688 if (JS_IP_MASK == (*itor & ALLOC_IP_MASK)) {
689 auto arktsFrameInfo = ParseArktsOfflineSymbolization(ipid, *itor);
690 if (!arktsFrameInfo) {
691 break;
692 }
693 result->emplace_back(arktsFrameInfo);
694 continue;
695 }
696 auto frameInfo = OfflineSymbolizationByIp(ipid, *itor);
697 // If the IP in the middle of the call stack cannot be symbolized, the remaining IP is discarded
698 if (!frameInfo) {
699 break;
700 }
701 result->emplace_back(frameInfo);
702 }
703 return result;
704 }
FillOfflineSymbolizationFrames(std::map<uint64_t,std::shared_ptr<std::vector<uint64_t>>>::iterator mapItor)705 void NativeHookFilter::FillOfflineSymbolizationFrames(
706 std::map<uint64_t, std::shared_ptr<std::vector<uint64_t>>>::iterator mapItor)
707 {
708 auto curCacheIpid = mapItor->second->back();
709 stackIdToCallChainIdMap_.insert(std::make_pair(mapItor->first, ++callChainId_));
710 auto framesInfo = OfflineSymbolization(mapItor->second);
711 uint16_t depth = 0;
712 if (isSingleProcData_) {
713 curCacheIpid = SINGLE_PROC_IPID;
714 }
715 uint64_t filePathIndex = INVALID_UINT64;
716 for (auto itor = framesInfo->rbegin(); itor != framesInfo->rend(); itor++) {
717 // Note that the filePathId here is provided for the end side. Not a true TS internal index dictionary.
718 auto frameInfo = itor->get();
719 filePathIndex = ipidToFilePathIdToFileIndex_.Find(curCacheIpid, frameInfo->filePathId_);
720 std::string vaddr = base::Uint64ToHexText(frameInfo->symVaddr_);
721 NativeHookFrameVaddrRow nativeHookFrameVaddrRow = {callChainId_,
722 depth++,
723 frameInfo->ip_,
724 frameInfo->symbolIndex_,
725 filePathIndex,
726 frameInfo->offset_,
727 frameInfo->symbolOffset_,
728 vaddr};
729 auto row = traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(nativeHookFrameVaddrRow);
730 UpdateFilePathIndexToCallStackRowMap(row, filePathIndex);
731 }
732 }
733
ReparseStacksWithDifferentMeans()734 void NativeHookFilter::ReparseStacksWithDifferentMeans()
735 {
736 for (auto itor = reparseStackIdToFramesMap_.begin(); itor != reparseStackIdToFramesMap_.end(); itor++) {
737 // Items with key equal to stack id should not be retained in stackIdToCallChainIdMap_
738 if (stackIdToCallChainIdMap_.count(itor->first)) {
739 TS_LOGE("error! The mapping of ambiguous call stack id and callChainId has not been deleted!");
740 }
741 FillOfflineSymbolizationFrames(itor);
742 }
743 reparseStackIdToFramesMap_.clear();
744 }
745
UpdateReparseStack(uint64_t stackId,std::shared_ptr<std::vector<uint64_t>> frames)746 void NativeHookFilter::UpdateReparseStack(uint64_t stackId, std::shared_ptr<std::vector<uint64_t>> frames)
747 {
748 // delete the stack ids whitch should be parsed again
749 if (stackIdToCallChainIdMap_.count(stackId)) {
750 stackIdToCallChainIdMap_.erase(stackId);
751 }
752 /* update reparseStackIdToFramesMap_. The reparseStackIdToFramesMap_ cannot be parsed immediately.
753 Wait until the relevant memmaps and symbolTable updates are completed. After the main event is
754 updated and before the main event is about to be parsed, parse reparseStackIdToFramesMap_ first. */
755 if (!stackIdToFramesMap_.count(stackId)) {
756 reparseStackIdToFramesMap_.emplace(std::make_pair(stackId, frames));
757 }
758 }
ReparseStacksWithAddrRange(uint64_t start,uint64_t end)759 inline void NativeHookFilter::ReparseStacksWithAddrRange(uint64_t start, uint64_t end)
760 {
761 // Get the list of call stack ids that should be parsed again
762 for (auto itor = allStackIdToFramesMap_.begin(); itor != allStackIdToFramesMap_.end(); itor++) {
763 auto ips = itor->second;
764 for (auto ipsItor = ips->begin(); ipsItor != ips->end(); ipsItor++) {
765 if (*ipsItor >= start && *ipsItor < end) {
766 UpdateReparseStack(itor->first, itor->second);
767 break;
768 }
769 }
770 }
771 }
772
773 // Only called in offline symbolization mode.
ParseMapsEvent(std::unique_ptr<NativeHookMetaData> & nativeHookMetaData)774 void NativeHookFilter::ParseMapsEvent(std::unique_ptr<NativeHookMetaData> &nativeHookMetaData)
775 {
776 segs_.emplace_back(nativeHookMetaData->seg_);
777 const ProtoReader::BytesView &mapsInfoByteView = nativeHookMetaData->reader_->maps_info();
778 if (traceDataCache_->isSplitFile_) {
779 auto hookData = commHookData_.datas->add_events();
780 MapsInfo *mapsInfo = hookData->mutable_maps_info();
781 mapsInfo->ParseFromArray(mapsInfoByteView.Data(), mapsInfoByteView.Size());
782 commHookData_.size += mapsInfoByteView.Size();
783 return;
784 }
785 auto reader = std::make_shared<ProtoReader::MapsInfo_Reader>(mapsInfoByteView);
786
787 // The temporary variable startAddr here is to solve the problem of parsing errors under the window platform
788 auto startAddr = reader->start();
789 auto endAddr = reader->end();
790 uint64_t start = INVALID_UINT64;
791 uint64_t end = INVALID_UINT64;
792 auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(reader->pid(), "");
793 if (isSingleProcData_) {
794 ipid = SINGLE_PROC_IPID;
795 }
796 // Get [start, end) of ips addr range which need to update
797 std::tie(start, end) = GetNeedUpdateProcessMapsAddrRange(ipid, startAddr, endAddr);
798 if (start != INVALID_UINT64 && start != end) { // Conflicting
799 /* First parse the updated call stacks, then parse the main events, and finally update Maps or SymbolTable
800 Note that when tsToMainEventsMap_.size() > MAX_CACHE_SIZE and main events need to be resolved, this logic
801 should also be followed. */
802 ParseFramesInOfflineSymbolizationMode();
803 // When a main event is updated, the call stack that needs to be parsed again is parsed.
804 if (tsToMainEventsMap_.size()) {
805 ReparseStacksWithDifferentMeans();
806 FilterNativeHookMainEvent(tsToMainEventsMap_.size());
807 }
808
809 // Delete IP symbolization results within the conflict range.
810 auto ipToFrameInfoPtr = const_cast<IpToFrameInfoType *>(ipidToIpToFrameInfo_.Find(ipid));
811 if (ipToFrameInfoPtr != nullptr) {
812 auto ipToFrameInfoItor = ipToFrameInfoPtr->lower_bound(start);
813 while (ipToFrameInfoItor != ipToFrameInfoPtr->end() && ipToFrameInfoItor->first < end) {
814 ipToFrameInfoItor = ipToFrameInfoPtr->erase(ipToFrameInfoItor);
815 }
816 }
817 // Delete MapsInfo within the conflict range
818 auto startAddrToMapsInfoMapPtr =
819 const_cast<StartAddrToMapsInfoType *>(ipidToStartAddrToMapsInfoMap_.Find(ipid));
820 if (startAddrToMapsInfoMapPtr != nullptr) {
821 auto itor = startAddrToMapsInfoMapPtr->lower_bound(start);
822 while (itor != startAddrToMapsInfoMapPtr->end() && itor->first < end) {
823 itor = startAddrToMapsInfoMapPtr->erase(itor);
824 }
825 }
826 ReparseStacksWithAddrRange(start, end);
827 }
828 ipidToStartAddrToMapsInfoMap_.Insert(ipid, startAddr, std::move(reader));
829 }
830 template <class T>
UpdateSymbolTablePtrAndStValueToSymAddrMap(T * firstSymbolAddr,const int size,std::shared_ptr<ProtoReader::SymbolTable_Reader> reader)831 void NativeHookFilter::UpdateSymbolTablePtrAndStValueToSymAddrMap(
832 T *firstSymbolAddr,
833 const int size,
834 std::shared_ptr<ProtoReader::SymbolTable_Reader> reader)
835 {
836 for (auto i = 0; i < size; i++) {
837 auto symAddr = firstSymbolAddr + i;
838 if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) {
839 symbolTablePtrAndStValueToSymAddr_.Insert(reader, symAddr->st_value,
840 reinterpret_cast<const uint8_t *>(symAddr));
841 }
842 }
843 }
GetIpRangeByIpidAndFilePathId(uint32_t ipid,uint32_t filePathId)844 std::tuple<uint64_t, uint64_t> NativeHookFilter::GetIpRangeByIpidAndFilePathId(uint32_t ipid, uint32_t filePathId)
845 {
846 uint64_t start = INVALID_UINT32;
847 uint64_t end = 0;
848 auto startAddrToMapsInfoMapPtr = ipidToStartAddrToMapsInfoMap_.Find(ipid);
849 if (startAddrToMapsInfoMapPtr != nullptr) {
850 for (auto itor = startAddrToMapsInfoMapPtr->begin(); itor != startAddrToMapsInfoMapPtr->end(); itor++) {
851 if (itor->second->file_path_id() == filePathId) {
852 start = std::min(itor->first, start);
853 end = std::max(itor->second->end(), end);
854 } else if (start != INVALID_UINT32) {
855 break;
856 }
857 }
858 }
859 return std::make_tuple(start, end);
860 }
DeleteFrameInfoWhichNeedsReparse(uint32_t ipid,uint32_t filePathId)861 void NativeHookFilter::DeleteFrameInfoWhichNeedsReparse(uint32_t ipid, uint32_t filePathId)
862 {
863 // Delete symbolic results with the same filePathId
864 auto ipToFrameInfoPtr = const_cast<IpToFrameInfoType *>(ipidToIpToFrameInfo_.Find(ipid));
865 if (ipToFrameInfoPtr != nullptr) {
866 for (auto itor = ipToFrameInfoPtr->begin(); itor != ipToFrameInfoPtr->end();) {
867 if (itor->second->filePathId_ == filePathId) {
868 itor = ipToFrameInfoPtr->erase(itor);
869 continue;
870 }
871 itor++;
872 }
873 }
874 }
ProcSymbolTable(uint32_t ipid,uint32_t filePathId,std::shared_ptr<ProtoReader::SymbolTable_Reader> reader)875 void NativeHookFilter::ProcSymbolTable(uint32_t ipid,
876 uint32_t filePathId,
877 std::shared_ptr<ProtoReader::SymbolTable_Reader> reader)
878 {
879 auto symbolTablePtr = ipidTofilePathIdToSymbolTableMap_.Find(ipid, filePathId);
880 if (symbolTablePtr != nullptr) { // SymbolTable already exists.
881 /* First parse the updated call stacks, then parse the main events, and finally update Maps or SymbolTable
882 Note that when tsToMainEventsMap_.size() > MAX_CACHE_SIZE and main events need to be resolved, this logic
883 should also be followed. */
884 ParseFramesInOfflineSymbolizationMode();
885 // When a main event is updated, the call stack that needs to be parsed again is parsed.
886 if (tsToMainEventsMap_.size()) {
887 ReparseStacksWithDifferentMeans();
888 FilterNativeHookMainEvent(tsToMainEventsMap_.size());
889 }
890 DeleteFrameInfoWhichNeedsReparse(ipid, filePathId);
891 uint64_t start = INVALID_UINT32;
892 uint64_t end = 0;
893 std::tie(start, end) = GetIpRangeByIpidAndFilePathId(ipid, filePathId);
894 ReparseStacksWithAddrRange(start, end);
895 symbolTablePtr = reader;
896 } else {
897 ipidTofilePathIdToSymbolTableMap_.Insert(ipid, filePathId, reader);
898 }
899 }
900 // Only called in offline symbolization mode.
ParseSymbolTableEvent(std::unique_ptr<NativeHookMetaData> & nativeHookMetaData)901 void NativeHookFilter::ParseSymbolTableEvent(std::unique_ptr<NativeHookMetaData> &nativeHookMetaData)
902 {
903 segs_.emplace_back(nativeHookMetaData->seg_);
904 const ProtoReader::BytesView &symbolTableByteView = nativeHookMetaData->reader_->symbol_tab();
905 if (traceDataCache_->isSplitFile_) {
906 auto hookData = commHookData_.datas->add_events();
907 SymbolTable *symbolTable = hookData->mutable_symbol_tab();
908 symbolTable->ParseFromArray(symbolTableByteView.Data(), symbolTableByteView.Size());
909 commHookData_.size += symbolTableByteView.Size();
910 return;
911 }
912 auto reader = std::make_shared<ProtoReader::SymbolTable_Reader>(symbolTableByteView);
913 auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(reader->pid(), "");
914 if (isSingleProcData_) {
915 ipid = SINGLE_PROC_IPID;
916 }
917 ProcSymbolTable(ipid, reader->file_path_id(), reader);
918 auto symEntrySize = reader->sym_entry_size();
919 auto symTable = reader->sym_table();
920 if (symEntrySize == 0) {
921 return;
922 }
923 auto size = symTable.Size() / symEntrySize;
924 if (symEntrySize == ELF32_SYM) {
925 UpdateSymbolTablePtrAndStValueToSymAddrMap(reinterpret_cast<const Elf32_Sym *>(symTable.Data()), size, reader);
926 } else {
927 UpdateSymbolTablePtrAndStValueToSymAddrMap(reinterpret_cast<const Elf64_Sym *>(symTable.Data()), size, reader);
928 }
929 }
930
MaybeUpdateCurrentSizeDur(uint64_t row,uint64_t timeStamp,bool isMalloc)931 void NativeHookFilter::MaybeUpdateCurrentSizeDur(uint64_t row, uint64_t timeStamp, bool isMalloc)
932 {
933 auto &lastAnyEventRaw = isMalloc ? traceDataCache_->GetNativeHookData()->GetLastMallocEventRaw()
934 : traceDataCache_->GetNativeHookData()->GetLastMmapEventRaw();
935 if (lastAnyEventRaw != INVALID_UINT64) {
936 traceDataCache_->GetNativeHookData()->UpdateCurrentSizeDur(lastAnyEventRaw, timeStamp);
937 }
938 lastAnyEventRaw = row;
939 }
940
941 // when symbolization failed, use filePath + vaddr as symbol name
UpdateSymbolIdsForSymbolizationFailed()942 void NativeHookFilter::UpdateSymbolIdsForSymbolizationFailed()
943 {
944 auto size = traceDataCache_->GetNativeHookFrameData()->Size();
945 for (size_t i = 0; i < size; ++i) {
946 auto symbolNameIndex = traceDataCache_->GetNativeHookFrameData()->SymbolNames()[i];
947 if (symbolNameIndex != INVALID_UINT64) {
948 continue;
949 }
950 auto filePathIndex = traceDataCache_->GetNativeHookFrameData()->FilePaths()[i];
951 if (filePathIndex != INVALID_UINT64) {
952 auto filePathStr = traceDataCache_->dataDict_.GetDataFromDict(filePathIndex);
953 auto vaddrStr = traceDataCache_->GetNativeHookFrameData()->Vaddrs()[i];
954 traceDataCache_->GetNativeHookFrameData()->UpdateSymbolId(
955 i, traceDataCache_->dataDict_.GetStringIndex(filePathStr + "+" + vaddrStr));
956 } else {
957 // when symbolization failed,filePath and symbolNameIndex invalid
958 auto ip = traceDataCache_->GetNativeHookFrameData()->Ips()[i];
959 // Distinguish whether it is the last layer call stack using the first 3 bytes
960 if (ALLOC_IP_MASK == (ip & ALLOC_IP_MASK)) {
961 // Take the last five bytes from the IP address
962 uint64_t ipBitOperation = ip & IP_BIT_OPERATION;
963 std::ostringstream newSymbol;
964 // alloc size (IP(Decimal))bytes 0xIP(hexadecimal conversion)
965 newSymbol << "alloc size(" << base::number(ipBitOperation, base::INTEGER_RADIX_TYPE_DEC) << "bytes)"
966 << "0x" << base::number(ip, base::INTEGER_RADIX_TYPE_HEX);
967 traceDataCache_->GetNativeHookFrameData()->UpdateSymbolId(
968 i, traceDataCache_->dataDict_.GetStringIndex(newSymbol.str()));
969 } else {
970 // If the current callChainId is same,unknow 0x ip(Convert IP to hexadecimal)
971 traceDataCache_->GetNativeHookFrameData()->UpdateSymbolId(
972 i, traceDataCache_->dataDict_.GetStringIndex("unknown 0x" +
973 base::number(ip, base::INTEGER_RADIX_TYPE_HEX)));
974 }
975 }
976 }
977 }
ParseFramesInOfflineSymbolizationMode()978 void NativeHookFilter::ParseFramesInOfflineSymbolizationMode()
979 {
980 for (auto stackIdToFramesItor = stackIdToFramesMap_.begin(); stackIdToFramesItor != stackIdToFramesMap_.end();
981 stackIdToFramesItor++) {
982 FillOfflineSymbolizationFrames(stackIdToFramesItor);
983 }
984 // In offline symbolization scenarios, The updated call stack information is saved in stackIdToFramesMap_.
985 // After each parsing is completed, it needs to be cleared to avoid repeated parsing.
986 stackIdToFramesMap_.clear();
987 }
988
GetNativeHookFrameVaddrs()989 void NativeHookFilter::GetNativeHookFrameVaddrs()
990 {
991 vaddrs_.clear();
992 auto size = traceDataCache_->GetNativeHookFrameData()->Size();
993 // Traverse every piece of native_hook frame data
994 for (size_t i = 0; i < size; i++) {
995 auto symbolOffset = traceDataCache_->GetNativeHookFrameData()->SymbolOffsets()[i];
996 auto fileOffset = traceDataCache_->GetNativeHookFrameData()->Offsets()[i];
997 auto ip = traceDataCache_->GetNativeHookFrameData()->Ips()[i];
998 // When the offset and symbolOffset is valid, vaddr = offset + symbolOffset
999 // Generally, when symbolOffset is a valid value, Fileoffset is also a valid value
1000 if (symbolOffset != INVALID_UINT64 && symbolOffset != 0 && fileOffset != INVALID_UINT64 && fileOffset != ip &&
1001 fileOffset != 0) {
1002 auto vaddr = base::Uint64ToHexText(fileOffset + symbolOffset);
1003 vaddrs_.emplace_back(vaddr);
1004 continue;
1005 }
1006 // When the offset and symbolOffset is invalid, vaddr takes the string after the plus sign in the function name
1007 auto functionNameIndex = traceDataCache_->GetNativeHookFrameData()->SymbolNames()[i];
1008 std::string vaddr = "";
1009 auto itor = functionNameIndexToVaddr_.find(functionNameIndex);
1010 if (itor == functionNameIndexToVaddr_.end()) {
1011 auto functionName = traceDataCache_->dataDict_.GetDataFromDict(functionNameIndex);
1012 auto pos = functionName.rfind("+");
1013 if (pos != functionName.npos && pos != functionName.length() - 1) {
1014 vaddr = functionName.substr(++pos);
1015 }
1016 // Vaddr keeps "" when lookup failed
1017 functionNameIndexToVaddr_.emplace(std::make_pair(functionNameIndex, vaddr));
1018 } else {
1019 vaddr = itor->second;
1020 }
1021 vaddrs_.emplace_back(vaddr);
1022 }
1023 }
1024 // Called When isCallStackCompressedMode_ is true && isOfflineSymbolizationMode_ is false.
ParseFramesInCallStackCompressedMode()1025 void NativeHookFilter::ParseFramesInCallStackCompressedMode()
1026 {
1027 for (auto stackIdToFramesItor = stackIdToFramesMap_.begin(); stackIdToFramesItor != stackIdToFramesMap_.end();
1028 stackIdToFramesItor++) {
1029 auto frameIds = stackIdToFramesItor->second;
1030 uint16_t depth = 0;
1031 auto curCacheIpid = frameIds->back();
1032 if (isSingleProcData_) {
1033 curCacheIpid = SINGLE_PROC_IPID;
1034 }
1035 for (auto frameIdsItor = frameIds->crbegin() + 1; frameIdsItor != frameIds->crend(); frameIdsItor++) {
1036 auto frameBytesPtr = ipidToFrameIdToFrameBytes_.Find(curCacheIpid, *frameIdsItor);
1037 if (frameBytesPtr == nullptr) {
1038 TS_LOGE("Can not find Frame by frame_map_id!!!");
1039 continue;
1040 }
1041 ProtoReader::Frame_Reader reader(*frameBytesPtr);
1042 if (!reader.has_file_path_id() or !reader.has_symbol_name_id()) {
1043 TS_LOGE("Data exception, frames should has fil_path_id and symbol_name_id");
1044 continue;
1045 }
1046 auto filePathIndex = ipidToFilePathIdToFileIndex_.Find(curCacheIpid, reader.file_path_id());
1047 if (filePathIndex == INVALID_UINT64) {
1048 TS_LOGE("Data exception, can not find fil_path_id(%u)!!!", reader.file_path_id());
1049 continue;
1050 }
1051 auto symbolIndex = ipidToSymIdToSymIndex_.Find(curCacheIpid, reader.symbol_name_id());
1052 if (symbolIndex == INVALID_UINT64) {
1053 TS_LOGE("Data exception, can not find symbol_name_id!!!");
1054 continue;
1055 }
1056 // IP may not exist
1057 // 0 is meaningful, but it is not displayed. Other data is still needed
1058 auto frameIp = reader.has_ip() ? reader.ip() : INVALID_UINT64;
1059 auto frameOffset = reader.has_offset() ? reader.offset() : INVALID_UINT64;
1060 auto frameSymbolOffset = reader.has_symbol_offset() ? reader.symbol_offset() : INVALID_UINT64;
1061 NativeHookFrameRow nativeHookFrameRow = {static_cast<uint32_t>(stackIdToFramesItor->first),
1062 depth++,
1063 frameIp,
1064 symbolIndex,
1065 filePathIndex,
1066 frameOffset,
1067 frameSymbolOffset};
1068 auto row = traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(nativeHookFrameRow);
1069 UpdateFilePathIndexToCallStackRowMap(row, filePathIndex);
1070 }
1071 }
1072 }
1073 // Called When isCallStackCompressedMode_ is false
ParseFramesWithOutCallStackCompressedMode()1074 void NativeHookFilter::ParseFramesWithOutCallStackCompressedMode()
1075 {
1076 for (auto itor = callChainIdToStackHashValueMap_.begin(); itor != callChainIdToStackHashValueMap_.end(); itor++) {
1077 auto callChainId = itor->first;
1078 if (!stackHashValueToFramesHashMap_.count(itor->second)) {
1079 continue;
1080 }
1081 auto &framesHash = stackHashValueToFramesHashMap_.at(itor->second);
1082 uint16_t depth = 0;
1083 for (auto frameHashValueVectorItor = framesHash.crbegin(); frameHashValueVectorItor != framesHash.crend();
1084 frameHashValueVectorItor++) {
1085 if (!frameHashToFrameInfoMap_.count(*frameHashValueVectorItor)) {
1086 TS_LOGE("find matching frameInfo failed!!!!");
1087 return;
1088 }
1089 auto &frameInfo = frameHashToFrameInfoMap_.at(*frameHashValueVectorItor);
1090 NativeHookFrameRow nativeHookFrameRow = {callChainId,
1091 depth++,
1092 frameInfo->ip_,
1093 frameInfo->symbolIndex_,
1094 frameInfo->filePathIndex_,
1095 frameInfo->offset_,
1096 frameInfo->symbolOffset_};
1097 auto row = traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(nativeHookFrameRow);
1098 UpdateFilePathIndexToCallStackRowMap(row, frameInfo->filePathIndex_);
1099 }
1100 }
1101 }
ParseSymbolizedNativeHookFrame()1102 void NativeHookFilter::ParseSymbolizedNativeHookFrame()
1103 {
1104 // isOfflineSymbolizationMode is false, but isCallStackCompressedMode is true.
1105 if (isCallStackCompressedMode_) {
1106 ParseFramesInCallStackCompressedMode();
1107 } else {
1108 ParseFramesWithOutCallStackCompressedMode();
1109 }
1110 GetNativeHookFrameVaddrs();
1111 traceDataCache_->GetNativeHookFrameData()->UpdateVaddrs(vaddrs_);
1112 return;
1113 }
UpdateThreadNameWithNativeHookData() const1114 void NativeHookFilter::UpdateThreadNameWithNativeHookData() const
1115 {
1116 if (itidToThreadNameId_.empty() || threadNameIdToThreadNameIndex_.empty()) {
1117 return;
1118 }
1119 for (auto itor = itidToThreadNameId_.begin(); itor != itidToThreadNameId_.end(); ++itor) {
1120 auto thread = traceDataCache_->GetThreadData(itor->first);
1121 if (!thread->nameIndex_) {
1122 auto threadNameMapItor = threadNameIdToThreadNameIndex_.find(itor->second);
1123 if (threadNameMapItor != threadNameIdToThreadNameIndex_.end()) {
1124 thread->nameIndex_ = threadNameMapItor->second;
1125 }
1126 }
1127 }
1128 }
FinishParseNativeHookData()1129 void NativeHookFilter::FinishParseNativeHookData()
1130 {
1131 // In offline symbolization mode Parse all NativeHook main events depends on updated stackIdToCallChainIdMap_
1132 // during execute ParseSymbolizedNativeHookFrame or ReparseStacksWithDifferentMeans , So first parse the call
1133 // stack data and then parse the main event.
1134 if (isOfflineSymbolizationMode_) {
1135 ParseFramesInOfflineSymbolizationMode();
1136 ReparseStacksWithDifferentMeans();
1137 UpdateSymbolIdsForSymbolizationFailed();
1138 }
1139 FilterNativeHookMainEvent(tsToMainEventsMap_.size());
1140 // In online symbolization mode and callstack is not compressed mode parse stack should after parse main event
1141 // In online symbolization mode and callstack is compressed mode, there is no need worry about the order
1142 if (!isOfflineSymbolizationMode_) {
1143 ParseSymbolizedNativeHookFrame();
1144 }
1145
1146 // update last lib id
1147 UpdateLastCallerPathAndSymbolIndexs();
1148 UpdateThreadNameWithNativeHookData();
1149 #if !defined(IS_WASM)
1150 // 统计模式数据冗余优化在wasm下关闭
1151 if (isStatisticMode_) {
1152 traceDataCache_->GetNativeHookFrameData()->ClearUselessCallChainIds(callChainIdsSet_);
1153 filePathIndexToFrameTableRowMap_.clear();
1154 const auto &vec = traceDataCache_->GetConstNativeHookFrameData().FilePaths();
1155 for (size_t i = 0; i < vec.size(); i++) {
1156 UpdateFilePathIndexToCallStackRowMap(i, vec[i]);
1157 }
1158 }
1159 #endif
1160 }
UpdateLastCallerPathAndSymbolIndexs()1161 void NativeHookFilter::UpdateLastCallerPathAndSymbolIndexs()
1162 {
1163 GetCallIdToLastLibId();
1164 if (isStatisticMode_) {
1165 traceDataCache_->GetNativeHookStatisticsData()->UpdateLastCallerPathAndSymbolIndexs(
1166 callIdToLastCallerPathIndex_);
1167 } else {
1168 traceDataCache_->GetNativeHookData()->UpdateLastCallerPathAndSymbolIndexs(callIdToLastCallerPathIndex_);
1169 }
1170 }
GetCallIdToLastLibId()1171 void NativeHookFilter::GetCallIdToLastLibId()
1172 {
1173 callIdToLastCallerPathIndex_.clear();
1174 auto size = static_cast<int64_t>(traceDataCache_->GetNativeHookFrameData()->Size());
1175 uint32_t lastCallChainId = INVALID_UINT32;
1176 bool foundLast = false;
1177 for (auto i = size - 1; i > -1; i--) {
1178 auto callChainId = traceDataCache_->GetNativeHookFrameData()->CallChainIds()[i];
1179 if (callChainId == lastCallChainId) {
1180 if (foundLast) {
1181 continue;
1182 }
1183 }
1184 if (callChainId != lastCallChainId) {
1185 lastCallChainId = callChainId;
1186 foundLast = false;
1187 }
1188 auto filePathIndex = traceDataCache_->GetNativeHookFrameData()->FilePaths()[i];
1189 if (filePathIndex == INVALID_UINT64) {
1190 continue;
1191 }
1192 auto symbolIndex = traceDataCache_->GetNativeHookFrameData()->SymbolNames()[i];
1193 if (!traceDataCache_->GetNativeHookFrameData()->Depths()[i]) {
1194 callIdToLastCallerPathIndex_.insert({callChainId, std::make_tuple(filePathIndex, symbolIndex)});
1195 foundLast = true;
1196 continue;
1197 }
1198
1199 auto lower = std::lower_bound(invalidLibPathIndexs_.begin(), invalidLibPathIndexs_.end(), filePathIndex);
1200 if (lower == invalidLibPathIndexs_.end() || *lower != filePathIndex) { // found
1201 auto filePath = traceDataCache_->dataDict_.GetDataFromDict(filePathIndex);
1202 auto ret = filePath.find("libc++_shared.so");
1203 if (ret == filePath.npos) {
1204 callIdToLastCallerPathIndex_.insert({callChainId, std::make_tuple(filePathIndex, symbolIndex)});
1205 foundLast = true;
1206 }
1207 }
1208 }
1209 }
1210
1211 template <class T>
UpdateFilePathIdAndStValueToSymAddrMap(T * firstSymbolAddr,const int size,uint32_t filePathId)1212 void NativeHookFilter::UpdateFilePathIdAndStValueToSymAddrMap(T *firstSymbolAddr, const int size, uint32_t filePathId)
1213 {
1214 for (auto i = 0; i < size; i++) {
1215 auto symAddr = firstSymbolAddr + i;
1216 if ((symAddr->st_info & STT_FUNC) && (symAddr->st_value)) {
1217 filePathIdAndStValueToSymAddr_.Insert(filePathId, symAddr->st_value,
1218 reinterpret_cast<const uint8_t *>(symAddr));
1219 }
1220 }
1221 }
1222
NativeHookReloadElfSymbolTable(const std::unique_ptr<SymbolsFile> & symbolsFile)1223 void NativeHookFilter::NativeHookReloadElfSymbolTable(const std::unique_ptr<SymbolsFile> &symbolsFile)
1224 {
1225 auto nativeHookFrame = traceDataCache_->GetNativeHookFrameData();
1226 auto size = nativeHookFrame->Size();
1227 auto filePathIndexs = nativeHookFrame->FilePaths();
1228 auto vaddrs = nativeHookFrame->Vaddrs();
1229 std::shared_ptr<std::set<size_t>> frameRows = nullptr;
1230 for (const auto &item : filePathIndexToFrameTableRowMap_) {
1231 auto filePath = traceDataCache_->GetDataFromDict(item.first);
1232 if (base::EndWith(filePath, symbolsFile->filePath_)) {
1233 frameRows = item.second;
1234 break;
1235 }
1236 }
1237 if (frameRows == nullptr) {
1238 return;
1239 }
1240 for (auto row : *frameRows) {
1241 auto symVaddr = base::StrToInt<uint32_t>(vaddrs[row], base::INTEGER_RADIX_TYPE_HEX);
1242 if (!symVaddr.has_value()) {
1243 continue;
1244 }
1245 auto dfxSymbol = symbolsFile->GetSymbolWithVaddr(symVaddr.value());
1246 if (dfxSymbol.IsValid()) {
1247 auto newSymbolIndex = traceDataCache_->GetDataIndex(dfxSymbol.GetName());
1248 nativeHookFrame->UpdateSymbolId(row, newSymbolIndex);
1249 }
1250 }
1251 UpdateLastCallerPathAndSymbolIndexs();
1252 }
UpdateFilePathIndexToCallStackRowMap(size_t row,DataIndex filePathIndex)1253 void NativeHookFilter::UpdateFilePathIndexToCallStackRowMap(size_t row, DataIndex filePathIndex)
1254 {
1255 if (filePathIndex != INVALID_UINT64) {
1256 if (filePathIndexToFrameTableRowMap_.count(filePathIndex) == 0) {
1257 auto rows = std::make_shared<std::set<size_t>>();
1258 rows->insert(row);
1259 filePathIndexToFrameTableRowMap_[filePathIndex] = rows;
1260 } else {
1261 filePathIndexToFrameTableRowMap_[filePathIndex]->insert(row);
1262 }
1263 }
1264 }
GetCommHookData()1265 CommHookData &NativeHookFilter::GetCommHookData()
1266 {
1267 return commHookData_;
1268 }
GetHookPluginData()1269 ProfilerPluginData *NativeHookFilter::GetHookPluginData()
1270 {
1271 return hookPluginData_.get();
1272 }
SerializeHookCommDataToString()1273 void NativeHookFilter::SerializeHookCommDataToString()
1274 {
1275 if (commHookData_.size == 0) {
1276 return;
1277 }
1278 std::string hookBuffer;
1279 commHookData_.datas->SerializeToString(&hookBuffer);
1280 hookPluginData_->set_data(hookBuffer);
1281 std::unique_ptr<std::string> pluginBuffer = std::make_unique<std::string>();
1282 hookPluginData_->SerializeToString(pluginBuffer.get());
1283 traceDataCache_->HookCommProtos().push_back(std::move(pluginBuffer));
1284 hookPluginData_->Clear();
1285 commHookData_.datas->Clear();
1286 commHookData_.size = 0;
1287 hookPluginData_->set_name("nativehook");
1288 }
1289 } // namespace TraceStreamer
1290 } // namespace SysTuning
1291