• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "htrace_native_hook_parser.h"
16 #include "clock_filter_ex.h"
17 #include "process_filter.h"
18 #include "stat_filter.h"
19 namespace SysTuning {
20 namespace TraceStreamer {
21 constexpr static uint32_t MAX_PROTO_BUFFER_SIZE = 4 * 1024 * 1024;
22 
HtraceNativeHookParser(TraceDataCache * dataCache,const TraceStreamerFilters * ctx)23 HtraceNativeHookParser::HtraceNativeHookParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx)
24     : EventParserBase(dataCache, ctx), nativeHookFilter_(std::make_unique<NativeHookFilter>(dataCache, ctx))
25 {
26 }
27 
~HtraceNativeHookParser()28 HtraceNativeHookParser::~HtraceNativeHookParser()
29 {
30     TS_LOGI("native hook data ts MIN:%llu, MAX:%llu", static_cast<unsigned long long>(GetPluginStartTime()),
31             static_cast<unsigned long long>(GetPluginEndTime()));
32     TS_LOGI("native real ts MIN:%llu, MAX:%llu", static_cast<unsigned long long>(MinTs()),
33             static_cast<unsigned long long>(MaxTs()));
34 }
35 
ParseStackMap(const ProtoReader::BytesView & bytesView)36 bool HtraceNativeHookParser::ParseStackMap(const ProtoReader::BytesView& bytesView)
37 {
38     if (traceDataCache_->isSplitFile_) {
39         auto hookData = nativeHookFilter_->GetCommHookData().datas->add_events();
40         StackMap* stackMap = hookData->mutable_stack_map();
41         stackMap->ParseFromArray(bytesView.Data(), bytesView.Size());
42         nativeHookFilter_->GetCommHookData().size += bytesView.Size();
43         return false;
44     }
45     ProtoReader::StackMap_Reader stackMapReader(bytesView);
46     bool parseError = false;
47     auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(stackMapReader.pid(), "");
48     // stores frames info. if offlineSymbolization is true, storing ips data, else storing FrameMap id.
49     std::vector<uint64_t> frames;
50     if (stackMapReader.has_frame_map_id()) {
51         auto itor = stackMapReader.frame_map_id(&parseError);
52         TS_CHECK_TRUE(!parseError, false, "Parse packed varInt in ParseStackMap function failed!!!");
53         while (itor) {
54             frames.emplace_back(*itor);
55             itor++;
56         }
57     } else if (stackMapReader.has_ip()) {
58         auto itor = stackMapReader.ip(&parseError);
59         TS_CHECK_TRUE(!parseError, false, "Parse packed varInt in ParseStackMap function failed!!!");
60         // OfflineSymbolization use ipidToStartAddrToMapsInfoMap_ Multi-process differentiation
61         while (itor) {
62             frames.emplace_back(*itor);
63             itor++;
64         }
65     }
66     nativeHookFilter_->AppendStackMaps(ipid, stackMapReader.id(), frames);
67     return true;
68 }
69 
ParseFrameMap(std::unique_ptr<NativeHookMetaData> & nativeHookMetaData)70 void HtraceNativeHookParser::ParseFrameMap(std::unique_ptr<NativeHookMetaData>& nativeHookMetaData)
71 {
72     segs_.emplace_back(nativeHookMetaData->seg_);
73     const ProtoReader::BytesView& frameMapByteView = nativeHookMetaData->reader_->frame_map();
74     if (traceDataCache_->isSplitFile_) {
75         auto hookData = nativeHookFilter_->GetCommHookData().datas->add_events();
76         FrameMap* frameMap = hookData->mutable_frame_map();
77         frameMap->ParseFromArray(frameMapByteView.Data(), frameMapByteView.Size());
78         nativeHookFilter_->GetCommHookData().size += frameMapByteView.Size();
79         return;
80     }
81     ProtoReader::FrameMap_Reader frameMapReader(frameMapByteView);
82     auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(frameMapReader.pid(), "");
83     // when callstack is compressed, Frame message only has ip data area.
84     nativeHookFilter_->AppendFrameMaps(ipid, frameMapReader.id(), frameMapReader.frame());
85 }
ParseFileEvent(const ProtoReader::BytesView & bytesView)86 void HtraceNativeHookParser::ParseFileEvent(const ProtoReader::BytesView& bytesView)
87 {
88     if (traceDataCache_->isSplitFile_) {
89         auto hookData = nativeHookFilter_->GetCommHookData().datas->add_events();
90         FilePathMap* filePathMap = hookData->mutable_file_path();
91         filePathMap->ParseFromArray(bytesView.Data(), bytesView.Size());
92         nativeHookFilter_->GetCommHookData().size += bytesView.Size();
93         return;
94     }
95     ProtoReader::FilePathMap_Reader filePathMapReader(bytesView);
96     auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(filePathMapReader.pid(), "");
97     auto nameIndex = traceDataCache_->dataDict_.GetStringIndex(filePathMapReader.name().ToStdString());
98     nativeHookFilter_->AppendFilePathMaps(ipid, filePathMapReader.id(), nameIndex);
99 }
ParseSymbolEvent(const ProtoReader::BytesView & bytesView)100 void HtraceNativeHookParser::ParseSymbolEvent(const ProtoReader::BytesView& bytesView)
101 {
102     if (traceDataCache_->isSplitFile_) {
103         auto hookData = nativeHookFilter_->GetCommHookData().datas->add_events();
104         SymbolMap* symbolMap = hookData->mutable_symbol_name();
105         symbolMap->ParseFromArray(bytesView.Data(), bytesView.Size());
106         nativeHookFilter_->GetCommHookData().size += bytesView.Size();
107         return;
108     }
109     ProtoReader::SymbolMap_Reader symbolMapReader(bytesView);
110     auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(symbolMapReader.pid(), "");
111     auto nameIndex = traceDataCache_->dataDict_.GetStringIndex(symbolMapReader.name().ToStdString());
112     nativeHookFilter_->AppendSymbolMap(ipid, symbolMapReader.id(), nameIndex);
113 }
ParseThreadEvent(const ProtoReader::BytesView & bytesView)114 void HtraceNativeHookParser::ParseThreadEvent(const ProtoReader::BytesView& bytesView)
115 {
116     if (traceDataCache_->isSplitFile_) {
117         auto hookData = nativeHookFilter_->GetCommHookData().datas->add_events();
118         ThreadNameMap* threadNameMap = hookData->mutable_thread_name_map();
119         threadNameMap->ParseFromArray(bytesView.Data(), bytesView.Size());
120         nativeHookFilter_->GetCommHookData().size += bytesView.Size();
121         return;
122     }
123     ProtoReader::ThreadNameMap_Reader threadNameMapReader(bytesView);
124     auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(threadNameMapReader.pid(), "");
125     auto nameIndex = traceDataCache_->GetDataIndex(threadNameMapReader.name().ToStdString());
126     nativeHookFilter_->AppendThreadNameMap(ipid, threadNameMapReader.id(), nameIndex);
127 }
128 
ParseNativeHookAuxiliaryEvent(std::unique_ptr<NativeHookMetaData> & nativeHookMetaData)129 void HtraceNativeHookParser::ParseNativeHookAuxiliaryEvent(std::unique_ptr<NativeHookMetaData>& nativeHookMetaData)
130 {
131     auto& reader = nativeHookMetaData->reader_;
132     if (reader->has_stack_map()) {
133         ParseStackMap(reader->stack_map());
134     } else if (reader->has_frame_map()) {
135         ParseFrameMap(nativeHookMetaData);
136     } else if (reader->has_file_path()) {
137         ParseFileEvent(reader->file_path());
138     } else if (reader->has_symbol_name()) {
139         ParseSymbolEvent(reader->symbol_name());
140     } else if (reader->has_thread_name_map()) {
141         ParseThreadEvent(reader->thread_name_map());
142     } else if (reader->has_maps_info()) {
143         nativeHookFilter_->ParseMapsEvent(nativeHookMetaData);
144     } else if (reader->has_symbol_tab()) {
145         nativeHookFilter_->ParseSymbolTableEvent(nativeHookMetaData);
146     } else if (reader->has_tag_event()) {
147         nativeHookFilter_->ParseTagEvent(reader->tag_event());
148     } else {
149         TS_LOGE("unsupported native_hook data!");
150     }
151 }
SplitHookData(std::unique_ptr<NativeHookMetaData> & nativeHookMetaData,bool & haveSplitSeg)152 void HtraceNativeHookParser::SplitHookData(std::unique_ptr<NativeHookMetaData>& nativeHookMetaData, bool& haveSplitSeg)
153 {
154     if (isCommData_ && hookBootTime_ <= traceDataCache_->SplitFileMinTime()) {
155         ParseNativeHookAuxiliaryEvent(nativeHookMetaData);
156     } else if (hookBootTime_ >= traceDataCache_->SplitFileMinTime() &&
157                hookBootTime_ <= traceDataCache_->SplitFileMaxTime()) {
158         haveSplitSeg = true;
159     }
160 }
161 // In order to improve the accuracy of data, it is necessary to sort the original data.
162 // Data sorting will be reduced by 5% to 10% Speed of parsing data.
Parse(HtraceDataSegment & dataSeg,bool & haveSplitSeg)163 void HtraceNativeHookParser::Parse(HtraceDataSegment& dataSeg, bool& haveSplitSeg)
164 {
165     auto batchNativeHookDataReader = ProtoReader::BatchNativeHookData_Reader(dataSeg.protoData);
166     for (auto itor = batchNativeHookDataReader.events(); itor; itor++) {
167         auto nativeHookDataReader = std::make_unique<ProtoReader::NativeHookData_Reader>(itor->ToBytes());
168         auto nativeHookMetaData = std::make_unique<NativeHookMetaData>(dataSeg.seg, std::move(nativeHookDataReader));
169         isCommData_ =
170             !(nativeHookMetaData->reader_->has_alloc_event() || nativeHookMetaData->reader_->has_free_event() ||
171               nativeHookMetaData->reader_->has_mmap_event() || nativeHookMetaData->reader_->has_munmap_event() ||
172               nativeHookMetaData->reader_->has_statistics_event());
173         hookBootTime_ = 0;
174         if (nativeHookMetaData->reader_->has_tv_sec() || nativeHookMetaData->reader_->has_tv_nsec()) {
175             auto timeStamp = nativeHookMetaData->reader_->tv_nsec() + nativeHookMetaData->reader_->tv_sec() * SEC_TO_NS;
176             hookBootTime_ = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, timeStamp);
177             UpdatePluginTimeRange(TS_CLOCK_REALTIME, timeStamp, hookBootTime_);
178         }
179         if (haveSplitSeg) {
180             return;
181         } else if (traceDataCache_->isSplitFile_) {
182             SplitHookData(nativeHookMetaData, haveSplitSeg);
183             continue;
184         }
185         if (!isCommData_ || nativeHookMetaData->reader_->has_tag_event()) {
186             nativeHookFilter_->MaybeParseNativeHookMainEvent(hookBootTime_, std::move(nativeHookMetaData));
187         } else {
188             ParseNativeHookAuxiliaryEvent(nativeHookMetaData);
189         }
190     }
191     if (!traceDataCache_->isSplitFile_ || nativeHookFilter_->GetCommHookData().size < MAX_PROTO_BUFFER_SIZE) {
192         return;
193     }
194     nativeHookFilter_->SerializeHookCommDataToString();
195 }
ParseConfigInfo(HtraceDataSegment & dataSeg)196 void HtraceNativeHookParser::ParseConfigInfo(HtraceDataSegment& dataSeg)
197 {
198     nativeHookFilter_->ParseConfigInfo(dataSeg.protoData);
199 }
FinishSplitNativeHook()200 void HtraceNativeHookParser::FinishSplitNativeHook()
201 {
202     nativeHookFilter_->SerializeHookCommDataToString();
203 }
FinishParseNativeHookData()204 void HtraceNativeHookParser::FinishParseNativeHookData()
205 {
206     nativeHookFilter_->FinishParseNativeHookData();
207 }
Finish()208 void HtraceNativeHookParser::Finish()
209 {
210     if (GetPluginStartTime() != GetPluginEndTime()) {
211         traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime());
212     } else {
213         traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginStartTime() + 1);
214     }
215 }
216 } // namespace TraceStreamer
217 } // namespace SysTuning
218