• 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 <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 #if !is_mingw
81 #ifndef O_BINARY
82 #define O_BINARY 0
83 #endif
84 #endif
85 
86 constexpr const double MS_DURATION =
87     static_cast<double>(std::chrono::milliseconds::duration::period::den);
88 
89 constexpr uint64_t KILO = 1024;
90 
91 namespace OHOS {
92 namespace Developtools {
93 namespace HiPerf {
94 std::string CanonicalizeSpecPath(const char* src);
95 const std::string EMPTY_STRING = "";
96 const ssize_t ERRINFOLEN = 512;
97 const std::string USER_DOMESTIC_BETA = "beta";
98 const std::set<int> ALLOW_UIDS = {1201};
99 
100 static const std::string USER_TYPE_PARAM = "const.logsystem.versiontype";
101 static const std::string USER_TYPE_PARAM_GET = "";
102 static const std::string SAVED_CMDLINES = "/sys/kernel/tracing/saved_cmdlines";
103 static FILE *outputDump_ = nullptr;
104 const uint64_t waitAppRunCheckTimeOut = 10;
105 
106 struct ThreadInfos {
107     pid_t tid;
108     pid_t pid;
109 };
110 // string function
111 class MemoryHold {
112 public:
~MemoryHold()113     ~MemoryHold()
114     {
115         Clean();
116     }
117     // only use in UT
Clean()118     void Clean()
119     {
120         for (auto &p : holder_) {
121             delete[] p;
122         }
123         holder_.clear();
124     }
Get()125     static MemoryHold &Get()
126     {
127         static MemoryHold instance;
128         return instance;
129     }
130 
131 private:
132     std::vector<char *> holder_;
133 };
134 
135 std::string StringReplace(std::string source, const std::string &from, const std::string &to);
136 
137 template<class T>
VectorToString(const std::vector<T> & items)138 std::string VectorToString(const std::vector<T> &items)
139 {
140     if constexpr (std::is_same<T, std::vector<std::string>>::value) {
141         std::vector<std::string> stringItems;
142         for (auto item : items) {
143             stringItems.push_back("[" + VectorToString(item) + "]");
144         }
145         return VectorToString(stringItems);
146     } else {
147         std::string itemsString;
148         const std::string split = ",";
149         for (auto item : items) {
150             if (!itemsString.empty())
151                 itemsString.append(split);
152             if constexpr (std::is_same<T, std::string>::value) {
153                 itemsString.append(item);
154             } else {
155                 itemsString.append(std::to_string(item));
156             }
157         }
158         if (itemsString.empty())
159             itemsString.append("<empty>");
160         return itemsString;
161     }
162 }
163 
164 std::string BufferToHexString(const std::vector<unsigned char> &vec);
165 std::string BufferToHexString(const unsigned char buf[], size_t size);
166 void HexDump(const void *buf, size_t size, size_t max_size = 0);
167 
168 std::string &StringTrim(std::string &s);
169 
170 std::vector<std::string> StringSplit(std::string source, const std::string split = ",");
171 
172 size_t SubStringCount(const std::string &source, const std::string &sub);
173 
174 bool StringStartsWith(const std::string &string, const std::string &with);
175 
176 bool StringEndsWith(const std::string &string, const std::string &with);
177 
178 bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName);
179 
180 std::vector<pid_t> GetSubthreadIDs(const pid_t pid);
181 
182 bool IsDigits(const std::string &str);
183 
184 bool IsHexDigits(const std::string &str);
185 
186 constexpr const int COMPRESS_READ_BUF_SIZE = 4096;
187 // compress specified dataFile into gzip file
188 bool CompressFile(const std::string &dataFile, const std::string &destFile);
189 // uncompress specified gzip file into dataFile
190 bool UncompressFile(const std::string &gzipFile, const std::string &dataFile);
191 
192 template<typename... VA>
StringPrintf(const char * stringFormat,VA...args)193 std::string StringPrintf(const char *stringFormat, VA... args)
194 {
195     // check howmany bytes we need
196     char bytes[DEFAULT_STRING_BUF_SIZE];
197     bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0';
198 
199     if (stringFormat == nullptr) {
200         return EMPTY_STRING;
201     }
202 
203     // print it to bytes
204     if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat,
205                    args...) < 0) {
206         return EMPTY_STRING;
207     }
208 
209     // make a string return
210     return std::string(bytes);
211 }
212 
213 // path check
214 std::vector<std::string> GetEntriesInDir(const std::string &basePath);
215 
216 std::vector<std::string> GetSubDirs(const std::string &basePath);
217 std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map);
218 
219 bool IsDir(const std::string &path);
220 
221 bool IsPath(const std::string &fileName);
222 
223 bool LittleMemory();
224 
225 #if defined(is_mingw) && is_mingw
226 const char PATH_SEPARATOR = '\\';
227 #else
228 const char PATH_SEPARATOR = '/';
229 #endif
230 const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
231 
232 std::string PlatformPathConvert(const std::string &path);
233 
234 // attribute
235 #define PACKED __attribute__((packed))
236 
237 // data align
238 
239 // some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu
240 #define HIPERF_BUF_ALIGN alignas(64)
241 
242 #define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1)))
243 
244 uint32_t RoundUp(uint32_t x, const int align);
245 
246 // data convert function
247 template<class T>
248 std::string ToHex(const T &source, int size = sizeof(T), bool prefix = false)
249 {
250     std::stringstream ss;
251     if (prefix) {
252         ss << "0x";
253     }
254     ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source;
255     return ss.str();
256 }
257 
258 // data move and copy
259 template<class S, class T>
260 size_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)
261 {
262     if (size == 0) {
263         size = sizeof(T);
264     }
265     if (memcpy_s(dest, size, buffer, size) != EOK) {
266         return size;
267     }
268     buffer = buffer + size;
269     return size;
270 }
271 
272 // file read write
273 bool ReadIntFromProcFile(const std::string &path, int &value);
274 bool WriteIntToProcFile(const std::string &path, int value);
275 std::string ReadFileToString(const std::string &fileName);
276 bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
277 bool WriteStringToFile(const std::string &fileName, const std::string &value);
278 
279 // stdout
280 class StdoutRecord {
281 public:
~StdoutRecord()282     ~StdoutRecord()
283     {
284         Stop(); // stdout need restore
285     }
286     StdoutRecord(const std::string &tempFile = EMPTY_STRING,
287                  const std::string &mode = EMPTY_STRING);
288 
289     bool Start();
290     std::string Stop();
291 
292 private:
293     OHOS::UniqueFd stdoutFile_;       // back and restore stdout
294     std::FILE *recordFile_ = nullptr; // save the output
295     bool stop_ = true;
296     std::string content_ = EMPTY_STRING;
297 };
298 
299 // misc
300 template<class T>
Percentage(const T & a,const T & b)301 float Percentage(const T &a, const T &b)
302 {
303     return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE;
304 }
305 
306 bool IsRoot();
307 bool IsBeta();
308 bool IsAllowProfilingUid();
309 bool PowerOfTwo(uint64_t n);
310 
311 const std::string HMKERNEL = "hmkernel";
312 
313 #define INDENT_ONE_LEVEL (indent + 1)
314 #define INDENT_TWO_LEVEL (indent + 2)
315 
316 #define PrintIndent(indent, format, ...)                                                           \
317     if (indent >= 0) {                                                                             \
318         if (outputDump_ == nullptr) {                                                              \
319             printf("%*s" format, (indent)*2, "", ##__VA_ARGS__);                                   \
320         } else {                                                                                   \
321             fprintf(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 IsSupportNonDebuggableApp();
339 const std::string GetUserType();
340 std::string GetProcessName(int pid);
341 bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
342 bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
343 
344 template <typename Func>
345 class ScopeGuard {
346 public:
ScopeGuard(Func && fn)347     ScopeGuard(Func&& fn)
348         : fn_(fn) {}
~ScopeGuard()349     ~ScopeGuard()
350     {
351         fn_();
352     }
353 private:
354     Func fn_;
355 };
356 
357 struct ScopeGuardOnExit {};
358 template <typename Func>
359 static inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func&& fn)
360 {
361     return ScopeGuard<Func>(std::forward<Func>(fn));
362 }
363 
364 #define ON_SCOPE_EXIT \
365         auto __onGuardExit__ = ScopeGuardOnExit{} + [&]
366 } // namespace HiPerf
367 } // namespace Developtools
368 } // namespace OHOS
369 
370 // this will also used for libunwind head (out of namespace)
371 #if defined(is_mingw) && is_mingw
372 #if !is_double_framework
373 #define HAVE_MMAP   1
374 #define MAP_PRIVATE 0x02
375 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset);
376 int munmap(void *addr, size_t);
377 #endif
378 #endif
379 
380 #endif // HIPERF_UTILITIES_H_
381