xref: /developtools/hiperf/include/utilities.h (revision 48f512ce)
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/*
49long long always 64 only in ILP64, int is 64 otherwise int is always 32
50*/
51using s8 = __s8;
52using u8 = __u8;
53using s16 = __s16;
54using u16 = __u16;
55using s32 = __s32;
56using u32 = __u32;
57using s64 = __s64;
58using u64 = __u64;
59
60constexpr const int NUMBER_FORMAT_HEX_BASE = 16;
61constexpr const int BYTE_PRINT_WIDTH = 2;
62constexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8;
63constexpr const int BITS_OF_BYTE = 8;
64constexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE;
65constexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE;
66constexpr const int FULL_PERCENTAGE = 100;
67constexpr const int FULL_PERCENTAGE_NUM_LEN = 5;      // 100.00
68constexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00
69constexpr const int FULL_PERCENTAGE_LEN = 6;          // 100.00%
70constexpr const int FULL_PERCENTAGE_DIFF_LEN = 7;     // +100.00%
71constexpr const int THOUSANDS = 1000;
72constexpr const int HUNDREDS = 100;
73constexpr const int DEFAULT_STRING_BUF_SIZE = 4096;
74constexpr const int FIVE_THOUSANDS = 5000;
75constexpr const int DATA_MAX_SIZE = 1001;
76constexpr const int LITTLE_MEMORY_SIZE = 1;
77constexpr const int MULTIPLE_SIZE = 1024;
78constexpr const uint16_t CHECK_FREQUENCY = 100; //
79constexpr const uint8_t CHECK_TIMEOUT = 30;
80constexpr const int INDENT_TWO = 2;
81constexpr const float ALMOST_ZERO = 0.001;
82#if !is_mingw
83#ifndef O_BINARY
84#define O_BINARY 0
85#endif
86#endif
87
88constexpr const double MS_DURATION =
89    static_cast<double>(std::chrono::milliseconds::duration::period::den);
90
91constexpr uint64_t KILO = 1024;
92
93namespace OHOS {
94namespace Developtools {
95namespace HiPerf {
96std::string CanonicalizeSpecPath(const char* src);
97const std::string EMPTY_STRING = "";
98const ssize_t ERRINFOLEN = 512;
99const std::set<int> ALLOW_UIDS = {1201};
100
101const std::string SAVED_CMDLINES = "/sys/kernel/tracing/saved_cmdlines";
102static FILE *g_outputDump = nullptr;
103const uint64_t waitAppRunCheckTimeOut = 20;
104
105struct ThreadInfos {
106    pid_t tid;
107    pid_t pid;
108};
109// string function
110class MemoryHold {
111public:
112    ~MemoryHold()
113    {
114        Clean();
115    }
116    // only use in UT
117    void Clean()
118    {
119        for (auto &p : holder_) {
120            delete[] p;
121        }
122        holder_.clear();
123    }
124    static MemoryHold &Get()
125    {
126        static MemoryHold instance;
127        return instance;
128    }
129
130private:
131    std::vector<char *> holder_;
132};
133
134std::string StringReplace(std::string source, const std::string &from, const std::string &to);
135
136template<class T>
137std::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
163std::string BufferToHexString(const std::vector<unsigned char> &vec);
164std::string BufferToHexString(const unsigned char buf[], size_t size);
165void HexDump(const void *buf, size_t size, size_t max_size = 0);
166
167std::string &StringTrim(std::string &s);
168
169std::vector<std::string> StringSplit(std::string source, const std::string &split = ",");
170
171size_t SubStringCount(const std::string &source, const std::string &sub);
172
173bool StringStartsWith(const std::string &string, const std::string &with);
174
175bool StringEndsWith(const std::string &string, const std::string &with);
176
177bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName);
178
179std::vector<pid_t> GetSubthreadIDs(const pid_t pid);
180
181bool IsDigits(const std::string &str);
182
183bool IsHexDigits(const std::string &str);
184
185constexpr const int COMPRESS_READ_BUF_SIZE = 4096;
186// compress specified dataFile into gzip file
187bool CompressFile(const std::string &dataFile, const std::string &destFile);
188// uncompress specified gzip file into dataFile
189bool UncompressFile(const std::string &gzipFile, const std::string &dataFile);
190
191template<typename... VA>
192std::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
213std::vector<std::string> GetEntriesInDir(const std::string &basePath);
214
215std::vector<std::string> GetSubDirs(const std::string &basePath);
216std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map);
217
218bool IsDir(const std::string &path);
219
220bool IsPath(const std::string &fileName);
221
222bool LittleMemory();
223
224#if defined(is_mingw) && is_mingw
225const char PATH_SEPARATOR = '\\';
226#else
227const char PATH_SEPARATOR = '/';
228#endif
229const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
230
231std::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
243uint32_t RoundUp(uint32_t x, const int align);
244
245// data convert function
246template<class T>
247std::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
258template<class S, class T>
259size_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
272bool ReadIntFromProcFile(const std::string &path, int &value);
273bool WriteIntToProcFile(const std::string &path, int value);
274std::string ReadFileToString(const std::string &fileName);
275bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
276bool WriteStringToFile(const std::string &fileName, const std::string &value);
277
278// stdout
279class StdoutRecord {
280public:
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
291private:
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
299template<class T>
300float 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
308bool IsRoot();
309bool IsBeta();
310bool IsAllowProfilingUid();
311bool IsHiviewCall();
312bool PowerOfTwo(uint64_t n);
313
314const 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
333pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
334                       const uint64_t waitAppTimeOut);
335bool IsRestarted(const std::string &appPackage);
336void CollectPidsByAppname(std::set<pid_t> &pids, const std::string &appPackage);
337bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs);
338bool IsExistDebugByApp(const std::string& bundleName);
339bool IsExistDebugByPid(const std::vector<pid_t> &pids);
340bool IsDebugableApp(const std::string& bundleName);
341bool IsSupportNonDebuggableApp();
342const std::string GetUserType();
343bool GetDeveloperMode();
344bool IsArkJsFile(const std::string& filepath);
345std::string GetProcessName(int pid);
346bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
347bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
348bool IsApplicationEncryped(const int pid);
349
350template <typename Func>
351class ScopeGuard {
352public:
353    explicit ScopeGuard(Func&& fn)
354        : fn_(fn) {}
355    ~ScopeGuard()
356    {
357        fn_();
358    }
359private:
360    Func fn_;
361};
362
363struct ScopeGuardOnExit {};
364template <typename Func>
365static 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