• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <unordered_set>
30 #include <vector>
31 #include <set>
32 
33 #include <dirent.h>
34 #include <fcntl.h>
35 #include <file_ex.h>
36 #include <stddef.h>
37 #include <sys/stat.h>
38 #include <unique_fd.h>
39 #include <unistd.h>
40 #if !is_mingw
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 template<class T>
SetToString(const std::unordered_set<T> & items)164 std::string SetToString(const std::unordered_set<T> &items)
165 {
166     std::string result = "";
167     const std::string split = ",";
168     for (auto item : items) {
169         if (!result.empty()) {
170             result.append(split);
171         }
172         if constexpr (std::is_same<T, std::string>::value) {
173             result.append(item);
174         } else {
175             result.append(std::to_string(item));
176         }
177     }
178     if (result.empty()) {
179         result.append("<empty>");
180     }
181     return result;
182 }
183 
184 std::string BufferToHexString(const std::vector<unsigned char> &vec);
185 std::string BufferToHexString(const unsigned char buf[], size_t size);
186 bool HexDump(const void *buf, size_t size, size_t max_size = 0);
187 
188 std::string &StringTrim(std::string &s);
189 
190 std::vector<std::string> StringSplit(std::string source, const std::string &split = ",");
191 
192 size_t SubStringCount(const std::string &source, const std::string &sub);
193 
194 bool StringStartsWith(const std::string &string, const std::string &with);
195 
196 bool StringEndsWith(const std::string &string, const std::string &with);
197 
198 bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName);
199 bool IsSameCommand(const std::string &cmdLine, const std::vector<std::string>& cmdNames);
200 
201 std::vector<pid_t> GetSubthreadIDs(const pid_t pid);
202 
203 bool IsDigits(const std::string &str);
204 
205 bool IsHexDigits(const std::string &str);
206 
207 constexpr const int COMPRESS_READ_BUF_SIZE = 4096;
208 // compress specified dataFile into gzip file
209 bool CompressFile(const std::string &dataFile, const std::string &destFile);
210 // uncompress specified gzip file into dataFile
211 bool UncompressFile(const std::string &gzipFile, const std::string &dataFile);
212 
213 template<typename... VA>
StringPrintf(const char * stringFormat,VA...args)214 std::string StringPrintf(const char *stringFormat, VA... args)
215 {
216     // check howmany bytes we need
217     char bytes[DEFAULT_STRING_BUF_SIZE];
218     bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0';
219 
220     if (stringFormat == nullptr) {
221         return EMPTY_STRING;
222     }
223 
224     // print it to bytes
225     if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat,
226                    args...) < 0) {
227         return EMPTY_STRING;
228     }
229 
230     // make a string return
231     return std::string(bytes);
232 }
233 
234 // path check
235 std::vector<std::string> GetEntriesInDir(const std::string &basePath);
236 
237 std::vector<std::string> GetSubDirs(const std::string &basePath);
238 std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map);
239 
240 bool IsDir(const std::string &path);
241 
242 bool IsPath(const std::string &fileName);
243 
244 bool LittleMemory();
245 
246 #if defined(is_mingw) && is_mingw
247 const char PATH_SEPARATOR = '\\';
248 #else
249 const char PATH_SEPARATOR = '/';
250 #endif
251 const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
252 
253 std::string PlatformPathConvert(const std::string &path);
254 
255 // attribute
256 #define PACKED __attribute__((packed))
257 
258 // data align
259 
260 // some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu
261 #define HIPERF_BUF_ALIGN alignas(64)
262 
263 #define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1)))
264 
265 uint32_t RoundUp(uint32_t x, const int align);
266 
267 // data convert function
268 template<class T>
269 std::string ToHex(const T &source, int size = sizeof(T), bool prefix = false)
270 {
271     std::stringstream ss;
272     if (prefix) {
273         ss << "0x";
274     }
275     ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source;
276     return ss.str();
277 }
278 
279 // data move and copy
280 template<class S, class T>
281 size_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)
282 {
283     if (size == 0) {
284         size = sizeof(T);
285     }
286     if (memcpy_s(dest, size, buffer, size) != EOK) {
287         return size;
288     }
289     buffer = buffer + size;
290     return size;
291 }
292 
293 // file read write
294 bool ReadIntFromProcFile(const std::string &path, int &value);
295 bool WriteIntToProcFile(const std::string &path, int value);
296 std::string ReadFileToString(const std::string &fileName);
297 bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
298 bool WriteStringToFile(const std::string &fileName, const std::string &value);
299 
300 // stdout
301 class StdoutRecord {
302 public:
~StdoutRecord()303     ~StdoutRecord()
304     {
305         Stop(); // stdout need restore
306     }
307     StdoutRecord(const std::string &tempFile = EMPTY_STRING,
308                  const std::string &mode = EMPTY_STRING);
309 
310     bool Start();
311     std::string Stop();
312 
313 private:
314     OHOS::UniqueFd stdoutFile_;       // back and restore stdout
315     std::FILE *recordFile_ = nullptr; // save the output
316     bool stop_ = true;
317     std::string content_ = EMPTY_STRING;
318 };
319 
320 // misc
321 template<class T>
Percentage(const T & a,const T & b)322 float Percentage(const T &a, const T &b)
323 {
324     if (b == 0) {
325         return 0;
326     }
327     return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE;
328 }
329 
330 bool IsRoot();
331 bool IsBeta();
332 bool IsAllowProfilingUid();
333 bool IsHiviewCall();
334 bool PowerOfTwo(uint64_t n);
335 bool IsNumeric(const std::string& str);
336 bool IscontainDigits(const std::string& str);
337 bool IsStringToIntSuccess(const std::string &str, int &num);
338 
339 const std::string HMKERNEL = "HongMeng";
340 
341 #define PRINT_INDENT(indent, format, ...)                                                          \
342     if (indent >= 0) {                                                                             \
343         if (g_outputDump == nullptr) {                                                             \
344             printf("%*s" format, (indent)*2, "", ##__VA_ARGS__);                                   \
345         } else {                                                                                   \
346             fprintf(g_outputDump, "%*s" format, (indent)*2, "", ##__VA_ARGS__);                    \
347         }                                                                                          \
348     } else {                                                                                       \
349         HLOGV("%s" format, "", ##__VA_ARGS__);                                                     \
350     }
351 
352 #ifndef MMAP_FAILED
353 #define MMAP_FAILED reinterpret_cast<void *>(-1)
354 #endif
355 #ifndef MAP_FAILED
356 #define MAP_FAILED MMAP_FAILED
357 #endif
358 pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
359                        const uint64_t waitAppTimeOut);
360 bool IsRestarted(const std::string &appPackage);
361 
362 template<typename Container>
CollectPidsByAppname(std::set<pid_t> & pids,const Container & appPackage)363 void CollectPidsByAppname(std::set<pid_t> &pids, const Container& appPackage)
364 {
365     const std::string basePath {"/proc/"};
366     const std::string cmdline {"/cmdline"};
367     std::vector<std::string> subDirs = GetSubDirs(basePath);
368     for (const auto &subDir : subDirs) {
369         if (!IsDigits(subDir)) {
370             continue;
371         }
372         std::string fileName {basePath + subDir + cmdline};
373         if (IsSameCommand(ReadFileToString(fileName), appPackage)) {
374             pids.emplace(std::stoul(subDir, nullptr));
375         }
376     }
377 }
378 
379 bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs);
380 bool IsExistDebugByApp(const std::string& bundleName, std::string& err);
381 bool IsExistDebugByPid(const std::vector<pid_t> &pids, std::string& err);
382 bool IsSupportNonDebuggableApp();
383 const std::string GetUserType();
384 bool GetDeveloperMode();
385 bool IsArkJsFile(const std::string& filepath);
386 std::string GetProcessName(int pid);
387 bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
388 bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
389 
390 template<typename T>
CheckOutOfRange(const T & value,const T & min,const T & max)391 inline bool CheckOutOfRange(const T& value, const T& min, const T& max)
392 {
393     return value < min || value > max;
394 }
395 
396 #define RETURN_IF(condition, retValue) do {         \
397     if (condition) {                                \
398         return retValue;                            \
399     }                                               \
400 } while (0)
401 
402 } // namespace HiPerf
403 } // namespace Developtools
404 } // namespace OHOS
405 #endif // HIPERF_UTILITIES_H_
406