1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 
21 #include <algorithm>
22 #include <cctype>
23 #include <cinttypes>
24 #include <cstdio>
25 #include <fstream>
26 #include <iomanip>
27 #include <iostream>
28 #include <sstream>
29 #include <string>
30 #include <vector>
31 #include <unordered_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 #include "debug_logger.h"
46 #include "noncopyable.h"
47 
48 // data and value
49 /*
50 long long always 64 only in ILP64, int is 64 otherwise int is always 32
51 */
52 using s8 = __s8;
53 using u8 = __u8;
54 using s16 = __s16;
55 using u16 = __u16;
56 using s32 = __s32;
57 using u32 = __u32;
58 using s64 = __s64;
59 using u64 = __u64;
60 
61 constexpr const int NUMBER_FORMAT_HEX_BASE = 16;
62 constexpr const int BYTE_PRINT_WIDTH = 2;
63 constexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8;
64 constexpr const int BITS_OF_BYTE = 8;
65 constexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE;
66 constexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE;
67 constexpr const int FULL_PERCENTAGE = 100;
68 constexpr const int FULL_PERCENTAGE_NUM_LEN = 5;      // 100.00
69 constexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00
70 constexpr const int FULL_PERCENTAGE_LEN = 6;          // 100.00%
71 constexpr const int FULL_PERCENTAGE_DIFF_LEN = 7;     // +100.00%
72 constexpr const int THOUSANDS = 1000;
73 constexpr const int HUNDREDS = 100;
74 constexpr const int DEFAULT_STRING_BUF_SIZE = 4096;
75 constexpr const int FIVE_THOUSANDS = 5000;
76 #if !is_mingw
77 #ifndef O_BINARY
78 #define O_BINARY 0
79 #endif
80 #endif
81 
82 constexpr const double MS_DUARTION =
83     static_cast<double>(std::chrono::milliseconds::duration::period::den);
84 
85 constexpr uint64_t KILO = 1024;
86 
87 namespace OHOS {
88 namespace Developtools {
89 namespace NativeDaemon {
90 namespace {
91 const std::string EMPTY_STRING = "";
92 constexpr int32_t STRING_POOL_SIZE = 4000;
93 }
94 
95 // string function
96 class StringViewMemoryHold {
97 public:
HoldStringView(const std::string& view)98     const char *HoldStringView(const std::string& view)
99     {
100         pthread_spin_lock(&spin_lock_);
101         const char* str = stringSet_.emplace(view).first->data();
102         pthread_spin_unlock(&spin_lock_);
103         return str;
104     };
105 
GetInstance()106     static StringViewMemoryHold& GetInstance()
107     {
108         static StringViewMemoryHold s;
109         return s;
110     }
111 
Clear()112     void Clear()
113     {
114         pthread_spin_lock(&spin_lock_);
115         stringSet_.clear();
116         pthread_spin_unlock(&spin_lock_);
117     }
118 
119 private:
StringViewMemoryHold()120     StringViewMemoryHold()
121     {
122         pthread_spin_init(&spin_lock_, PTHREAD_PROCESS_PRIVATE);
123     }
~StringViewMemoryHold()124     ~StringViewMemoryHold()
125     {
126         pthread_spin_destroy(&spin_lock_);
127     }
128     std::unordered_set<std::string> stringSet_{STRING_POOL_SIZE};
129     pthread_spinlock_t spin_lock_;
130 };
131 
132 std::string StringReplace(std::string source, const std::string &from, const std::string &to);
133 
134 template<class T>
VectorToString(const std::vector<T> &items)135 std::string VectorToString(const std::vector<T> &items)
136 {
137     if constexpr (std::is_same<T, std::vector<std::string>>::value) {
138         std::vector<std::string> stringItems;
139         for (auto item : items) {
140             stringItems.push_back("[" + VectorToString(item) + "]");
141         }
142         return VectorToString(stringItems);
143     } else {
144         std::string itemsString;
145         const std::string split = ",";
146         for (auto& item : items) {
147             if (!itemsString.empty())
148                 itemsString.append(split);
149             if constexpr (std::is_same<T, std::string>::value) {
150                 itemsString.append(item);
151             } else {
152                 itemsString.append(std::to_string(item));
153             }
154         }
155         if (itemsString.empty())
156             itemsString.append("<empty>");
157         return itemsString;
158     }
159 }
160 
161 std::string BufferToHexString(const std::vector<unsigned char> &vec);
162 std::string BufferToHexString(const unsigned char buf[], size_t size);
163 void HexDump(const uint8_t *buf, size_t size, size_t max_size = 0);
164 
165 std::string &StringTrim(std::string &s);
166 
167 std::vector<std::string> StringSplit(std::string source, std::string split = ",");
168 
169 void AdvancedSplitString(const std::string_view& str, const std::string& delimiters, std::vector<std::string>& elems);
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(std::string cmdLine, 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), DEFAULT_STRING_BUF_SIZE - 1, stringFormat, args...) < 0) {
204         return EMPTY_STRING;
205     }
206 
207     // make a string return
208     return std::string(bytes);
209 }
210 
211 // path check
212 std::vector<std::string> GetEntriesInDir(const std::string &basePath);
213 
214 std::vector<std::string> GetSubDirs(const std::string &basePath);
215 
216 bool IsDir(const std::string &path);
217 
218 bool IsPath(const std::string &fileName);
219 
220 #if is_mingw
221 const char PATH_SEPARATOR = '\\';
222 #else
223 const char PATH_SEPARATOR = '/';
224 #endif
225 const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
226 
227 std::string PlatformPathConvert(const std::string &path);
228 
229 // attribute
230 #define PACKED __attribute__((packed))
231 
232 // data align
233 
234 // some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu
235 #define HIPERF_BUF_ALIGN alignas(64)
236 
237 uint32_t RoundUp(uint32_t x, const int align);
238 
239 // data convert funcion
240 template<class T>
ToHex(const T &source, int size = sizeof(T), bool perfix = false)241 std::string ToHex(const T &source, int size = sizeof(T), bool perfix = false)
242 {
243     std::stringstream ss;
244     if (perfix) {
245         ss << "0x";
246     }
247     ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source;
248     return ss.str();
249 }
250 
251 // data move and copy
252 template<class S, class T>
CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)253 size_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)
254 {
255     if (size == 0) {
256         size = sizeof(T);
257     }
258     if (memcpy_s(dest, size, buffer, size) != EOK) {
259         return size;
260     }
261     buffer = buffer + size;
262     return size;
263 }
264 
265 // file read write
266 bool ReadIntFromProcFile(const std::string &path, int &value);
267 bool WriteIntToProcFile(const std::string &path, int value);
268 std::string ReadFileToString(const std::string &fileName);
269 bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
270 bool WriteStringToFile(const std::string &fileName, const std::string &value);
271 
272 // stdout
273 class StdoutRecord {
274 public:
~StdoutRecord()275     ~StdoutRecord()
276     {
277         Stop(); // stdout need restore
278     }
279     StdoutRecord(const std::string &tempFile = EMPTY_STRING,
280                  const std::string &mode = EMPTY_STRING);
281 
282     bool Start();
283     std::string Stop();
284 
285 private:
286     OHOS::UniqueFd stdoutFile_;       // back and restore stdout
287     std::FILE *recordFile_ = nullptr; // save the output
288     bool stop_ = true;
289     std::string content_ = EMPTY_STRING;
290 };
291 
292 // misc
293 template<class T>
Percentage(const T &a, const T &b)294 float Percentage(const T &a, const T &b)
295 {
296     return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE;
297 }
298 
299 bool IsRoot();
300 bool PowerOfTwo(int n);
301 
302 #define INDENT_ONE_LEVEL (indent + 1)
303 #define INDENT_TWO_LEVEL (indent + 2)
304 
305 #define PrintIndent(indent, format, ...)                                                           \
306     if (indent >= 0) {                                                                             \
307         printf("%*s" format, (indent)*2, "", ##__VA_ARGS__);                                       \
308     } else {                                                                                       \
309         HLOGV("%s" format, "", ##__VA_ARGS__);                                                     \
310     }
311 
312 #ifndef MMAP_FAILED
313 #define MMAP_FAILED (reinterpret_cast<void *>(-1))
314 #endif
315 #ifndef MAP_FAILED
316 #define MAP_FAILED MMAP_FAILED
317 #endif
318 int32_t GetProcessPid(const std::string& processName);
319 bool IsArkJsFile(const std::string& filepath);
320 } // namespace NativeDaemon
321 } // namespace Developtools
322 } // namespace OHOS
323 
324 // this will also used for libunwind head (out of namespace)
325 #if is_mingw
326 #define HAVE_MMAP   1
327 #define MAP_PRIVATE 0x02
328 #define PROT_NONE   0
329 #define PROT_READ   1
330 #define PROT_WRITE  2
331 #define PROT_EXEC   4
332 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset);
333 int munmap(void *addr, size_t);
334 #endif
335 
336 #endif
337