1 /*
2 * Copyright (c) 2025 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 #ifndef LPERF_EVENT_RECORD_H
16 #define LPERF_EVENT_RECORD_H
17
18 #include <cstdint>
19 #include <linux/perf_event.h>
20 #include <securec.h>
21 #include <string>
22 #include "dfx_log.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 constexpr uint32_t RECORD_SIZE_LIMIT = 65535;
27 constexpr ssize_t ERRINFOLEN = 512;
28
29 struct LperfRecordSampleData {
30 uint32_t pid = 0;
31 uint32_t tid = 0; /* if PERF_SAMPLE_TID */
32 uint64_t time = 0; /* if PERF_SAMPLE_TIME */
33 uint64_t nr = 0; /* if PERF_SAMPLE_CALLCHAIN */
34 uint64_t* ips = nullptr; /* if PERF_SAMPLE_CALLCHAIN */
35 };
36
StringFormat(const char * fmt,...)37 inline std::string StringFormat(const char* fmt, ...)
38 {
39 va_list vargs;
40 char buf[1024] = {0}; // 1024: buf size
41 std::string format(fmt);
42 va_start(vargs, fmt);
43 if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format.c_str(), vargs) < 0) {
44 va_end(vargs);
45 return "";
46 }
47
48 va_end(vargs);
49 return buf;
50 }
51
52 class LperfRecordSample {
53 public:
54 LperfRecordSampleData data_ = {};
55 LperfRecordSample() = default;
56
57 const char* GetName();
58 uint32_t GetType() const;
59 bool Init(uint8_t* data);
60 void Clear();
61 protected:
62 void InitHeader(uint8_t* data);
63
64 private:
65 struct perf_event_header header_ = {};
66 uint64_t sampleType_ = PERF_SAMPLE_TID | PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_TIME;
67 };
68
69 class LperfRecordFactory {
70 public:
71 static LperfRecordSample& GetLperfRecord(uint32_t type, uint8_t* data);
72 static void ClearData();
73
74 private:
75 static LperfRecordSample record_;
76 };
77
78 template<typename T>
79 bool PopFromBinary(bool condition, uint8_t*& data, T& dest, uint64_t& size);
80
81 template<typename T1, typename T2>
82 bool PopFromBinary2(bool condition, uint8_t*& data, T1& dest1, T2& dest2, uint64_t& size);
83
84 bool SetPointerOffset(uint8_t*& data, uint64_t offset, uint64_t& size);
85
86 #define NO_RETVAL /* retval */
87 #ifndef CHECK_TRUE_AND_RET
88 #define CHECK_TRUE_AND_RET(condition, retval, fmt, ...) \
89 do { \
90 if (!(condition)) [[unlikely]] { \
91 std::string str = StringFormat(fmt, ##__VA_ARGS__); \
92 DFXLOGE("%{public}s", str.c_str()); \
93 return retval; \
94 } \
95 } while (0)
96 #endif
97
98 #ifndef CHECK_ERR
99 #define CHECK_ERR(err, fmt, ...) \
100 do { \
101 if (err < 0) [[unlikely]] { \
102 char errInfo[ERRINFOLEN] = { 0 }; \
103 strerror_r(errno, errInfo, ERRINFOLEN); \
104 DFXLOGE("%{public}s, error: %{public}d, errInfo: %{public}s", \
105 StringFormat(fmt, ##__VA_ARGS__).c_str(), errno, errInfo); \
106 return false; \
107 } \
108 } while (0)
109 #endif
110 } // namespace HiviewDFX
111 } // namespace OHOS
112 #endif // LPERF_EVENT_RECORD_H