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