1 /*
2 * Copyright (c) 2021-2022 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 HIPERF_UTILITIES_H_
16 #define HIPERF_UTILITIES_H_
17
18 // for security function
19 #include <securec.h>
20 #include <algorithm>
21 #include <cctype>
22 #include <cinttypes>
23 #include <cstdio>
24 #include <fstream>
25 #include <iomanip>
26 #include <iostream>
27 #include <sstream>
28 #include <string>
29 #include <vector>
30 #include <set>
31
32 #include <dirent.h>
33 #include <fcntl.h>
34 #include <file_ex.h>
35 #include <stddef.h>
36 #include <sys/stat.h>
37 #include <unique_fd.h>
38 #include <unistd.h>
39 #if !is_mingw
40 #include <gtest/gtest_prod.h>
41 #include <sys/syscall.h>
42 #endif
43 #include <linux/types.h>
44 #include "debug_logger.h"
45 #include "noncopyable.h"
46
47 // data and value
48 /*
49 long long always 64 only in ILP64, int is 64 otherwise int is always 32
50 */
51 using s8 = __s8;
52 using u8 = __u8;
53 using s16 = __s16;
54 using u16 = __u16;
55 using s32 = __s32;
56 using u32 = __u32;
57 using s64 = __s64;
58 using u64 = __u64;
59
60 constexpr const int NUMBER_FORMAT_HEX_BASE = 16;
61 constexpr const int BYTE_PRINT_WIDTH = 2;
62 constexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8;
63 constexpr const int BITS_OF_BYTE = 8;
64 constexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE;
65 constexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE;
66 constexpr const int FULL_PERCENTAGE = 100;
67 constexpr const int FULL_PERCENTAGE_NUM_LEN = 5; // 100.00
68 constexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00
69 constexpr const int FULL_PERCENTAGE_LEN = 6; // 100.00%
70 constexpr const int FULL_PERCENTAGE_DIFF_LEN = 7; // +100.00%
71 constexpr const int THOUSANDS = 1000;
72 constexpr const int HUNDREDS = 100;
73 constexpr const int DEFAULT_STRING_BUF_SIZE = 4096;
74 constexpr const int FIVE_THOUSANDS = 5000;
75 constexpr const int DATA_MAX_SIZE = 1001;
76 constexpr const int LITTLE_MEMORY_SIZE = 1;
77 constexpr const int MULTIPLE_SIZE = 1024;
78 constexpr const uint16_t CHECK_FREQUENCY = 100; //
79 constexpr const uint8_t CHECK_TIMEOUT = 30;
80 constexpr const int INDENT_TWO = 2;
81 constexpr const float ALMOST_ZERO = 0.001;
82 #if !is_mingw
83 #ifndef O_BINARY
84 #define O_BINARY 0
85 #endif
86 #endif
87
88 constexpr const double MS_DURATION =
89 static_cast<double>(std::chrono::milliseconds::duration::period::den);
90
91 constexpr uint64_t KILO = 1024;
92
93 namespace OHOS {
94 namespace Developtools {
95 namespace HiPerf {
96 std::string CanonicalizeSpecPath(const char* src);
97 const std::string EMPTY_STRING = "";
98 const ssize_t ERRINFOLEN = 512;
99 const std::set<int> ALLOW_UIDS = {1201};
100
101 const std::string SAVED_CMDLINES = "/sys/kernel/tracing/saved_cmdlines";
102 static FILE *g_outputDump = nullptr;
103 const uint64_t waitAppRunCheckTimeOut = 20;
104
105 struct ThreadInfos {
106 pid_t tid;
107 pid_t pid;
108 };
109 // string function
110 class MemoryHold {
111 public:
~MemoryHold()112 ~MemoryHold()
113 {
114 Clean();
115 }
116 // only use in UT
Clean()117 void Clean()
118 {
119 for (auto &p : holder_) {
120 delete[] p;
121 }
122 holder_.clear();
123 }
Get()124 static MemoryHold &Get()
125 {
126 static MemoryHold instance;
127 return instance;
128 }
129
130 private:
131 std::vector<char *> holder_;
132 };
133
134 std::string StringReplace(std::string source, const std::string &from, const std::string &to);
135
136 template<class T>
VectorToString(const std::vector<T> &items)137 std::string VectorToString(const std::vector<T> &items)
138 {
139 if constexpr (std::is_same<T, std::vector<std::string>>::value) {
140 std::vector<std::string> stringItems;
141 for (auto item : items) {
142 stringItems.push_back("[" + VectorToString(item) + "]");
143 }
144 return VectorToString(stringItems);
145 } else {
146 std::string itemsString;
147 const std::string split = ",";
148 for (auto item : items) {
149 if (!itemsString.empty())
150 itemsString.append(split);
151 if constexpr (std::is_same<T, std::string>::value) {
152 itemsString.append(item);
153 } else {
154 itemsString.append(std::to_string(item));
155 }
156 }
157 if (itemsString.empty())
158 itemsString.append("<empty>");
159 return itemsString;
160 }
161 }
162
163 std::string BufferToHexString(const std::vector<unsigned char> &vec);
164 std::string BufferToHexString(const unsigned char buf[], size_t size);
165 void HexDump(const void *buf, size_t size, size_t max_size = 0);
166
167 std::string &StringTrim(std::string &s);
168
169 std::vector<std::string> StringSplit(std::string source, const std::string &split = ",");
170
171 size_t SubStringCount(const std::string &source, const std::string &sub);
172
173 bool StringStartsWith(const std::string &string, const std::string &with);
174
175 bool StringEndsWith(const std::string &string, const std::string &with);
176
177 bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName);
178
179 std::vector<pid_t> GetSubthreadIDs(const pid_t pid);
180
181 bool IsDigits(const std::string &str);
182
183 bool IsHexDigits(const std::string &str);
184
185 constexpr const int COMPRESS_READ_BUF_SIZE = 4096;
186 // compress specified dataFile into gzip file
187 bool CompressFile(const std::string &dataFile, const std::string &destFile);
188 // uncompress specified gzip file into dataFile
189 bool UncompressFile(const std::string &gzipFile, const std::string &dataFile);
190
191 template<typename... VA>
StringPrintf(const char *stringFormat, VA... args)192 std::string StringPrintf(const char *stringFormat, VA... args)
193 {
194 // check howmany bytes we need
195 char bytes[DEFAULT_STRING_BUF_SIZE];
196 bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0';
197
198 if (stringFormat == nullptr) {
199 return EMPTY_STRING;
200 }
201
202 // print it to bytes
203 if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat,
204 args...) < 0) {
205 return EMPTY_STRING;
206 }
207
208 // make a string return
209 return std::string(bytes);
210 }
211
212 // path check
213 std::vector<std::string> GetEntriesInDir(const std::string &basePath);
214
215 std::vector<std::string> GetSubDirs(const std::string &basePath);
216 std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map);
217
218 bool IsDir(const std::string &path);
219
220 bool IsPath(const std::string &fileName);
221
222 bool LittleMemory();
223
224 #if defined(is_mingw) && is_mingw
225 const char PATH_SEPARATOR = '\\';
226 #else
227 const char PATH_SEPARATOR = '/';
228 #endif
229 const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
230
231 std::string PlatformPathConvert(const std::string &path);
232
233 // attribute
234 #define PACKED __attribute__((packed))
235
236 // data align
237
238 // some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu
239 #define HIPERF_BUF_ALIGN alignas(64)
240
241 #define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1)))
242
243 uint32_t RoundUp(uint32_t x, const int align);
244
245 // data convert function
246 template<class T>
ToHex(const T &source, int size = sizeof(T), bool prefix = false)247 std::string ToHex(const T &source, int size = sizeof(T), bool prefix = false)
248 {
249 std::stringstream ss;
250 if (prefix) {
251 ss << "0x";
252 }
253 ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source;
254 return ss.str();
255 }
256
257 // data move and copy
258 template<class S, class T>
CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)259 size_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)
260 {
261 if (size == 0) {
262 size = sizeof(T);
263 }
264 if (memcpy_s(dest, size, buffer, size) != EOK) {
265 return size;
266 }
267 buffer = buffer + size;
268 return size;
269 }
270
271 // file read write
272 bool ReadIntFromProcFile(const std::string &path, int &value);
273 bool WriteIntToProcFile(const std::string &path, int value);
274 std::string ReadFileToString(const std::string &fileName);
275 bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
276 bool WriteStringToFile(const std::string &fileName, const std::string &value);
277
278 // stdout
279 class StdoutRecord {
280 public:
~StdoutRecord()281 ~StdoutRecord()
282 {
283 Stop(); // stdout need restore
284 }
285 StdoutRecord(const std::string &tempFile = EMPTY_STRING,
286 const std::string &mode = EMPTY_STRING);
287
288 bool Start();
289 std::string Stop();
290
291 private:
292 OHOS::UniqueFd stdoutFile_; // back and restore stdout
293 std::FILE *recordFile_ = nullptr; // save the output
294 bool stop_ = true;
295 std::string content_ = EMPTY_STRING;
296 };
297
298 // misc
299 template<class T>
Percentage(const T &a, const T &b)300 float Percentage(const T &a, const T &b)
301 {
302 if (b == 0) {
303 return 0;
304 }
305 return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE;
306 }
307
308 bool IsRoot();
309 bool IsBeta();
310 bool IsAllowProfilingUid();
311 bool IsHiviewCall();
312 bool PowerOfTwo(uint64_t n);
313
314 const std::string HMKERNEL = "HongMeng";
315
316 #define PRINT_INDENT(indent, format, ...) \
317 if (indent >= 0) { \
318 if (g_outputDump == nullptr) { \
319 printf("%*s" format, (indent)*2, "", ##__VA_ARGS__); \
320 } else { \
321 fprintf(g_outputDump, "%*s" format, (indent)*2, "", ##__VA_ARGS__); \
322 } \
323 } else { \
324 HLOGV("%s" format, "", ##__VA_ARGS__); \
325 }
326
327 #ifndef MMAP_FAILED
328 #define MMAP_FAILED reinterpret_cast<void *>(-1)
329 #endif
330 #ifndef MAP_FAILED
331 #define MAP_FAILED MMAP_FAILED
332 #endif
333 pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
334 const uint64_t waitAppTimeOut);
335 bool IsRestarted(const std::string &appPackage);
336 void CollectPidsByAppname(std::set<pid_t> &pids, const std::string &appPackage);
337 bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs);
338 bool IsExistDebugByApp(const std::string& bundleName);
339 bool IsExistDebugByPid(const std::vector<pid_t> &pids);
340 bool IsDebugableApp(const std::string& bundleName);
341 bool IsSupportNonDebuggableApp();
342 const std::string GetUserType();
343 bool GetDeveloperMode();
344 bool IsArkJsFile(const std::string& filepath);
345 std::string GetProcessName(int pid);
346 bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
347 bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
348 bool IsApplicationEncryped(const int pid);
349
350 template <typename Func>
351 class ScopeGuard {
352 public:
ScopeGuard(Func&& fn)353 explicit ScopeGuard(Func&& fn)
354 : fn_(fn) {}
~ScopeGuard()355 ~ScopeGuard()
356 {
357 fn_();
358 }
359 private:
360 Func fn_;
361 };
362
363 struct ScopeGuardOnExit {};
364 template <typename Func>
operator +(ScopeGuardOnExit, Func&& fn)365 static inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func&& fn)
366 {
367 return ScopeGuard<Func>(std::forward<Func>(fn));
368 }
369
370 #define ON_SCOPE_EXIT \
371 auto __onGuardExit__ = ScopeGuardOnExit{} + [&]
372 } // namespace HiPerf
373 } // namespace Developtools
374 } // namespace OHOS
375 #endif // HIPERF_UTILITIES_H_
376