1 /*
2  * Copyright (c) 2023 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 
16 #include "decoded/decoded_event.h"
17 
18 #include <functional>
19 #include <securec.h>
20 #include <sstream>
21 #include <unordered_map>
22 
23 #include "base/raw_data_base_def.h"
24 #include "decoded/raw_data_decoder.h"
25 #include "hiview_logger.h"
26 
27 namespace OHOS {
28 namespace HiviewDFX {
29 namespace EventRaw {
30 DEFINE_LOG_TAG("HiView-DecodedEvent");
31 namespace {
32 constexpr size_t MAX_BLOCK_SIZE = 384 * 1024; // 384K
33 constexpr size_t MAX_PARAM_CNT = 128 + 10; // 128 for Write, 10 for hiview
34 
TransUInt64ToFixedLengthStr(uint64_t src)35 std::string TransUInt64ToFixedLengthStr(uint64_t src)
36 {
37     const size_t maxIdLen = 20;
38     std::string uint64Str = std::to_string(src);
39     if (uint64Str.size() >= maxIdLen) {
40         return uint64Str;
41     }
42     std::string dest(maxIdLen, '0');
43     dest.replace(maxIdLen - uint64Str.size(), uint64Str.size(), uint64Str);
44     return dest;
45 }
46 }
47 
DecodedEvent(uint8_t * src)48 DecodedEvent::DecodedEvent(uint8_t* src)
49 {
50     if (src == nullptr) {
51         return;
52     }
53     size_t blockSize = static_cast<size_t>(*(reinterpret_cast<int32_t*>(src)));
54     if (blockSize < GetValidDataMinimumByteCount() || blockSize > MAX_BLOCK_SIZE) {
55         HIVIEW_LOGE("size of raw data is %{public}zu, which is invalid.", blockSize);
56         return;
57     }
58     rawData_ = new(std::nothrow) uint8_t[blockSize];
59     if (rawData_ == nullptr) {
60         return;
61     }
62     auto ret = memcpy_s(rawData_, blockSize, src, blockSize);
63     if (ret != EOK) {
64         HIVIEW_LOGE("Decode memory copy failed, ret is %{public}d.", ret);
65         delete[] rawData_;
66         return;
67     }
68     Parse();
69 }
70 
~DecodedEvent()71 DecodedEvent::~DecodedEvent()
72 {
73     if (rawData_ != nullptr) {
74         delete[] rawData_;
75         rawData_ = nullptr;
76     }
77 }
78 
AppendBaseInfo(std::stringstream & ss)79 void DecodedEvent::AppendBaseInfo(std::stringstream& ss)
80 {
81     char* domain = new(std::nothrow) char[MAX_DOMAIN_LENGTH + 1];
82     if (domain == nullptr) {
83         return;
84     }
85     if (memcpy_s(domain, MAX_DOMAIN_LENGTH, header_.domain, MAX_DOMAIN_LENGTH) != EOK) {
86         delete[] domain;
87         return;
88     }
89     domain[MAX_DOMAIN_LENGTH] = '\0';
90     auto eventDomain = std::string(domain);
91     AppendValue(ss, BASE_INFO_KEY_DOMAIN, eventDomain);
92     delete[] domain;
93     char* name = new(std::nothrow) char[MAX_EVENT_NAME_LENGTH + 1];
94     if (name == nullptr) {
95         return;
96     }
97     if (memcpy_s(name, MAX_EVENT_NAME_LENGTH, header_.name, MAX_EVENT_NAME_LENGTH) != EOK) {
98         delete[] name;
99         return;
100     }
101     name[MAX_EVENT_NAME_LENGTH] = '\0';
102     auto eventName = std::string(name);
103     AppendValue(ss, BASE_INFO_KEY_NAME, eventName);
104     delete[] name;
105     AppendValue(ss, BASE_INFO_KEY_TYPE, (static_cast<int>(header_.type) + 1)); // header_.type is only 2 bits which has
106                                                                           // been subtracted 1 before wrote.
107     AppendValue(ss, BASE_INFO_KEY_TIME_STAMP, header_.timestamp);
108     auto timeZone = ParseTimeZone(static_cast<size_t>(header_.timeZone));
109     AppendValue(ss, BASE_INFO_KEY_TIME_ZONE, timeZone);
110     AppendValue(ss, BASE_INFO_KEY_PID, header_.pid);
111     AppendValue(ss, BASE_INFO_KEY_TID, header_.tid);
112     AppendValue(ss, BASE_INFO_KEY_UID, header_.uid);
113     AppendValue(ss, BASE_INFO_KEY_LOG, static_cast<uint32_t>(header_.log));
114     AppendValue(ss, BASE_INFO_KEY_ID, TransUInt64ToFixedLengthStr(header_.id));
115     if (header_.isTraceOpened == 1) {
116         AppendValue(ss, BASE_INFO_KEY_TRACE_FLAG, static_cast<int>(traceInfo_.traceFlag));
117         AppendValue(ss, BASE_INFO_KEY_TRACE_ID, TransNumToHexStr(traceInfo_.traceId));
118         AppendValue(ss, BASE_INFO_KEY_SPAN_ID, TransNumToHexStr(traceInfo_.spanId));
119         AppendValue(ss, BASE_INFO_KEY_PARENT_SPAN_ID, TransNumToHexStr(traceInfo_.pSpanId));
120     }
121 }
122 
AppendCustomizedArrayParam(std::stringstream & ss,std::shared_ptr<DecodedParam> param)123 void DecodedEvent::AppendCustomizedArrayParam(std::stringstream& ss, std::shared_ptr<DecodedParam> param)
124 {
125     std::unordered_map<DataCodedType, std::function<void(std::shared_ptr<DecodedParam>)>> allFuncs = {
126         {DataCodedType::UNSIGNED_VARINT_ARRAY, [this, &ss](std::shared_ptr<DecodedParam> param) {
127                 std::vector<uint64_t> u64Vec;
128                 if (param->AsUint64Vec(u64Vec)) {
129                     this->AppendValue(ss, param->GetKey(), u64Vec);
130                 }
131             }
132         },
133         {DataCodedType::SIGNED_VARINT_ARRAY, [this, &ss](std::shared_ptr<DecodedParam> param) {
134                 std::vector<int64_t> i64Vec;
135                 if (param->AsInt64Vec(i64Vec)) {
136                     this->AppendValue(ss, param->GetKey(), i64Vec);
137                 }
138             }
139         },
140         {DataCodedType::FLOATING_ARRAY, [this, &ss](std::shared_ptr<DecodedParam> param) {
141                 std::vector<double> dVec;
142                 if (param->AsDoubleVec(dVec)) {
143                     this->AppendValue(ss, param->GetKey(), dVec);
144                 }
145             }
146         },
147         {DataCodedType::DSTRING_ARRAY, [this, &ss](std::shared_ptr<DecodedParam> param) {
148                 std::vector<std::string> strVec;
149                 if (param->AsStringVec(strVec)) {
150                     this->AppendValue(ss, param->GetKey(), strVec);
151                 }
152             }
153         }
154     };
155     auto iter = allFuncs.find(param->GetDataCodedType());
156     if (iter == allFuncs.end()) {
157         return;
158     }
159     iter->second(param);
160 }
161 
AppendCustomizedParam(std::stringstream & ss,std::shared_ptr<DecodedParam> param)162 void DecodedEvent::AppendCustomizedParam(std::stringstream& ss, std::shared_ptr<DecodedParam> param)
163 {
164     std::unordered_map<DataCodedType, std::function<void(std::shared_ptr<DecodedParam>)>> allFuncs = {
165         {DataCodedType::UNSIGNED_VARINT, [this, &ss](std::shared_ptr<DecodedParam> param) {
166                 uint64_t uint64DecodedVal;
167                 if (param->AsUint64(uint64DecodedVal)) {
168                     this->AppendValue(ss, param->GetKey(), uint64DecodedVal);
169                 }
170             }
171         },
172         {DataCodedType::SIGNED_VARINT, [this, &ss](std::shared_ptr<DecodedParam> param) {
173                 int64_t int64DecodedVal;
174                 if (param->AsInt64(int64DecodedVal)) {
175                     this->AppendValue(ss, param->GetKey(), int64DecodedVal);
176                 }
177             }
178         },
179         {DataCodedType::FLOATING, [this, &ss](std::shared_ptr<DecodedParam> param) {
180                 double dDecodedVal;
181                 if (param->AsDouble(dDecodedVal)) {
182                     this->AppendValue(ss, param->GetKey(), dDecodedVal);
183                 }
184             }
185         },
186         {DataCodedType::DSTRING, [this, &ss](std::shared_ptr<DecodedParam> param) {
187                 std::string strDecodedVal;
188                 if (param->AsString(strDecodedVal)) {
189                     this->AppendValue(ss, param->GetKey(), strDecodedVal);
190                 }
191             }
192         }
193     };
194     auto iter = allFuncs.find(param->GetDataCodedType());
195     if (iter == allFuncs.end()) {
196         return;
197     }
198     iter->second(param);
199 }
200 
AppendCustomizedParams(std::stringstream & ss)201 void DecodedEvent::AppendCustomizedParams(std::stringstream& ss)
202 {
203     for (auto param: allParams_) {
204         if (param == nullptr) {
205             continue;
206         }
207         std::vector<DataCodedType> noArrayEncodedTypes = {
208             DataCodedType::UNSIGNED_VARINT,
209             DataCodedType::SIGNED_VARINT,
210             DataCodedType::FLOATING,
211             DataCodedType::DSTRING,
212         };
213         if (find(noArrayEncodedTypes.begin(), noArrayEncodedTypes.end(), param->GetDataCodedType()) !=
214             noArrayEncodedTypes.end()) {
215             AppendCustomizedParam(ss, param);
216             continue;
217         }
218         AppendCustomizedArrayParam(ss, param);
219     }
220 }
221 
AsJsonStr()222 std::string DecodedEvent::AsJsonStr()
223 {
224     std::stringstream jsonStream;
225     jsonStream << "{";
226     AppendBaseInfo(jsonStream);
227     AppendCustomizedParams(jsonStream);
228     if (jsonStream.tellp() != 0) {
229         jsonStream.seekp(-1, std::ios_base::end);
230     }
231     jsonStream << "}";
232     return jsonStream.str();
233 }
234 
GetRawData()235 std::shared_ptr<RawData> DecodedEvent::GetRawData()
236 {
237     return std::make_shared<RawData>(rawData_, pos_);
238 }
239 
IsValid()240 bool DecodedEvent::IsValid()
241 {
242     return isValid_;
243 }
244 
GetHeader()245 const struct HiSysEventHeader& DecodedEvent::GetHeader()
246 {
247     return header_;
248 }
249 
GetTraceInfo()250 const struct TraceInfo& DecodedEvent::GetTraceInfo()
251 {
252     return traceInfo_;
253 }
254 
GetAllCustomizedValues()255 const std::vector<std::shared_ptr<DecodedParam>>& DecodedEvent::GetAllCustomizedValues()
256 {
257     return allParams_;
258 }
259 
Parse()260 void DecodedEvent::Parse()
261 {
262     isValid_ = true;
263     if (rawData_ == nullptr) {
264         isValid_ = false;
265         return;
266     }
267     pos_ = 0; // reset to 0
268     // decode block size
269     size_t blockSize = static_cast<size_t>(*(reinterpret_cast<int32_t*>(rawData_)));
270     pos_ += sizeof(int32_t);
271     ParseHeader(blockSize);
272     ParseCustomizedParams(blockSize);
273 }
274 
ParseHeader(const size_t maxLen)275 void DecodedEvent::ParseHeader(const size_t maxLen)
276 {
277     // decode event header
278     if ((pos_ + sizeof(struct HiSysEventHeader)) > maxLen) {
279         isValid_ = false;
280         return;
281     }
282     header_ = *(reinterpret_cast<struct HiSysEventHeader*>(rawData_ + pos_));
283     pos_ += sizeof(struct HiSysEventHeader);
284     // decode trace info
285     if (header_.isTraceOpened == 1) { // 1: include trace info, 0: exclude trace info
286         if (((pos_ + sizeof(struct TraceInfo)) > maxLen)) {
287             isValid_ = false;
288             return;
289         }
290         traceInfo_ = *(reinterpret_cast<struct TraceInfo*>(rawData_ + pos_));
291         pos_ += sizeof(struct TraceInfo);
292     }
293 }
294 
ParseCustomizedParams(const size_t maxLen)295 void DecodedEvent::ParseCustomizedParams(const size_t maxLen)
296 {
297     if ((pos_ + sizeof(int32_t)) > maxLen) {
298         isValid_ = false;
299         return;
300     }
301     auto paramCnt = static_cast<size_t>(*(reinterpret_cast<int32_t*>(rawData_ + pos_)));
302     if (paramCnt > MAX_PARAM_CNT) {
303         HIVIEW_LOGW("invalid param cnt=%{public}zu.", paramCnt);
304         isValid_ = false;
305         return;
306     }
307     pos_ += sizeof(int32_t);
308     while (paramCnt > 0) {
309         auto decodedParam = ParseCustomizedParam(maxLen);
310         if (decodedParam == nullptr || !(decodedParam->DecodeValue())) {
311             HIVIEW_LOGE("Value of customized parameter is decoded failed.");
312             isValid_ = false;
313             return;
314         }
315         pos_ = decodedParam->GetPosition();
316         allParams_.emplace_back(decodedParam);
317         --paramCnt;
318     }
319 }
320 
CreateFloatingNumTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)321 std::shared_ptr<DecodedParam> DecodedEvent::CreateFloatingNumTypeDecodedParam(const size_t maxLen,
322     const std::string& key, bool isArray)
323 {
324     if (isArray) {
325         return std::make_shared<FloatingNumberDecodedArrayParam>(rawData_, maxLen, pos_, key);
326     }
327     return std::make_shared<FloatingNumberDecodedParam>(rawData_, maxLen, pos_, key);
328 }
329 
CreateSignedVarintTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)330 std::shared_ptr<DecodedParam> DecodedEvent::CreateSignedVarintTypeDecodedParam(const size_t maxLen,
331     const std::string& key, bool isArray)
332 {
333     if (isArray) {
334         return std::make_shared<SignedVarintDecodedArrayParam>(rawData_, maxLen, pos_, key);
335     }
336     return std::make_shared<SignedVarintDecodedParam>(rawData_, maxLen, pos_, key);
337 }
338 
CreateStringTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)339 std::shared_ptr<DecodedParam> DecodedEvent::CreateStringTypeDecodedParam(const size_t maxLen,
340     const std::string& key, bool isArray)
341 {
342     if (isArray) {
343         return std::make_shared<StringDecodedArrayParam>(rawData_, maxLen, pos_, key);
344     }
345     return std::make_shared<StringDecodedParam>(rawData_, maxLen, pos_, key);
346 }
347 
CreateUnsignedVarintTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)348 std::shared_ptr<DecodedParam> DecodedEvent::CreateUnsignedVarintTypeDecodedParam(const size_t maxLen,
349     const std::string& key, bool isArray)
350 {
351     if (isArray) {
352         return std::make_shared<UnsignedVarintDecodedArrayParam>(rawData_, maxLen, pos_, key);
353     }
354     return std::make_shared<UnsignedVarintDecodedParam>(rawData_, maxLen, pos_, key);
355 }
356 
ParseCustomizedParam(const size_t maxLen)357 std::shared_ptr<DecodedParam> DecodedEvent::ParseCustomizedParam(const size_t maxLen)
358 {
359     std::string key;
360     if (!RawDataDecoder::StringValueDecoded(rawData_, maxLen, pos_, key)) {
361         isValid_ = false;
362         return nullptr;
363     }
364     struct ParamValueType valueType {
365         .isArray = 0,
366         .valueType = static_cast<uint8_t>(ValueType::UNKNOWN),
367         .valueByteCnt = 0,
368     };
369     if (!RawDataDecoder::ValueTypeDecoded(rawData_, maxLen, pos_, valueType)) {
370         isValid_ = false;
371         return nullptr;
372     }
373     std::shared_ptr<DecodedParam> ret = nullptr;
374     switch (ValueType(valueType.valueType)) {
375         case ValueType::STRING: {
376             ret = CreateStringTypeDecodedParam(maxLen, key, valueType.isArray == 1);
377             break;
378         }
379         case ValueType::FLOAT:
380         case ValueType::DOUBLE: {
381             ret = CreateFloatingNumTypeDecodedParam(maxLen, key, valueType.isArray == 1);
382             break;
383         }
384         case ValueType::UINT8:
385         case ValueType::UINT16:
386         case ValueType::UINT32:
387         case ValueType::UINT64: {
388             ret = CreateUnsignedVarintTypeDecodedParam(maxLen, key, valueType.isArray == 1);
389             break;
390         }
391         case ValueType::BOOL:
392         case ValueType::INT8:
393         case ValueType::INT16:
394         case ValueType::INT32:
395         case ValueType::INT64: {
396             ret = CreateSignedVarintTypeDecodedParam(maxLen, key, valueType.isArray == 1);
397             break;
398         }
399         default:
400             break;
401     }
402     return ret;
403 }
404 } // namespace EventRaw
405 } // namespace HiviewDFX
406 } // namespace OHOS