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