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