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