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