• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "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