2021-12-24 08:46:38 +00:00
|
|
|
/*
|
2022-03-07 07:07:57 +00:00
|
|
|
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
2021-12-24 08:46:38 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
#ifndef HIPERF_UTILITIES_H_
|
|
|
|
#define HIPERF_UTILITIES_H_
|
|
|
|
|
|
|
|
// for security function
|
|
|
|
#include <securec.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cctype>
|
|
|
|
#include <cinttypes>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2023-04-14 03:50:56 +00:00
|
|
|
#include <set>
|
2021-12-24 08:46:38 +00:00
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <file_ex.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unique_fd.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#if !is_mingw
|
|
|
|
#include <gtest/gtest_prod.h>
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
#endif
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include "debug_logger.h"
|
|
|
|
#include "noncopyable.h"
|
|
|
|
|
|
|
|
// data and value
|
|
|
|
/*
|
|
|
|
long long always 64 only in ILP64, int is 64 otherwise int is always 32
|
|
|
|
*/
|
|
|
|
using s8 = __s8;
|
|
|
|
using u8 = __u8;
|
|
|
|
using s16 = __s16;
|
|
|
|
using u16 = __u16;
|
|
|
|
using s32 = __s32;
|
|
|
|
using u32 = __u32;
|
|
|
|
using s64 = __s64;
|
|
|
|
using u64 = __u64;
|
|
|
|
|
|
|
|
constexpr const int NUMBER_FORMAT_HEX_BASE = 16;
|
|
|
|
constexpr const int BYTE_PRINT_WIDTH = 2;
|
|
|
|
constexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8;
|
|
|
|
constexpr const int BITS_OF_BYTE = 8;
|
|
|
|
constexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE;
|
|
|
|
constexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE;
|
|
|
|
constexpr const int FULL_PERCENTAGE = 100;
|
|
|
|
constexpr const int FULL_PERCENTAGE_NUM_LEN = 5; // 100.00
|
|
|
|
constexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00
|
|
|
|
constexpr const int FULL_PERCENTAGE_LEN = 6; // 100.00%
|
|
|
|
constexpr const int FULL_PERCENTAGE_DIFF_LEN = 7; // +100.00%
|
|
|
|
constexpr const int THOUSANDS = 1000;
|
|
|
|
constexpr const int HUNDREDS = 100;
|
|
|
|
constexpr const int DEFAULT_STRING_BUF_SIZE = 4096;
|
|
|
|
constexpr const int FIVE_THOUSANDS = 5000;
|
2022-09-28 06:56:45 +00:00
|
|
|
constexpr const int DATA_MAX_SIZE = 1001;
|
2023-05-24 06:23:29 +00:00
|
|
|
constexpr const int LITTLE_MEMORY_SIZE = 1;
|
|
|
|
constexpr const int MULTIPLE_SIZE = 1024;
|
2023-09-05 09:53:57 +00:00
|
|
|
constexpr const uint16_t CHECK_FREQUENCY = 100; //
|
|
|
|
constexpr const uint8_t CHECK_TIMEOUT = 30;
|
2024-05-08 12:07:36 +00:00
|
|
|
constexpr const int INDENT_TWO = 2;
|
2024-08-23 03:17:18 +00:00
|
|
|
constexpr const float ALMOST_ZERO = 0.001;
|
2021-12-24 08:46:38 +00:00
|
|
|
#if !is_mingw
|
|
|
|
#ifndef O_BINARY
|
|
|
|
#define O_BINARY 0
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2023-08-26 08:20:03 +00:00
|
|
|
constexpr const double MS_DURATION =
|
2021-12-24 08:46:38 +00:00
|
|
|
static_cast<double>(std::chrono::milliseconds::duration::period::den);
|
|
|
|
|
|
|
|
constexpr uint64_t KILO = 1024;
|
|
|
|
|
|
|
|
namespace OHOS {
|
|
|
|
namespace Developtools {
|
|
|
|
namespace HiPerf {
|
2022-02-18 07:42:09 +00:00
|
|
|
std::string CanonicalizeSpecPath(const char* src);
|
2021-12-24 08:46:38 +00:00
|
|
|
const std::string EMPTY_STRING = "";
|
2022-02-18 07:42:09 +00:00
|
|
|
const ssize_t ERRINFOLEN = 512;
|
2023-04-14 03:50:56 +00:00
|
|
|
const std::set<int> ALLOW_UIDS = {1201};
|
|
|
|
|
2024-05-08 03:21:09 +00:00
|
|
|
const std::string SAVED_CMDLINES = "/sys/kernel/tracing/saved_cmdlines";
|
|
|
|
static FILE *g_outputDump = nullptr;
|
2024-08-04 02:19:08 +00:00
|
|
|
const uint64_t waitAppRunCheckTimeOut = 20;
|
2021-12-24 08:46:38 +00:00
|
|
|
|
2023-06-06 09:22:53 +00:00
|
|
|
struct ThreadInfos {
|
|
|
|
pid_t tid;
|
|
|
|
pid_t pid;
|
|
|
|
};
|
2021-12-24 08:46:38 +00:00
|
|
|
// string function
|
2021-12-29 14:26:17 +00:00
|
|
|
class MemoryHold {
|
2021-12-24 08:46:38 +00:00
|
|
|
public:
|
2021-12-29 14:26:17 +00:00
|
|
|
~MemoryHold()
|
2021-12-24 08:46:38 +00:00
|
|
|
{
|
2021-12-29 14:26:17 +00:00
|
|
|
Clean();
|
2021-12-24 08:46:38 +00:00
|
|
|
}
|
2021-12-29 14:26:17 +00:00
|
|
|
// only use in UT
|
|
|
|
void Clean()
|
|
|
|
{
|
|
|
|
for (auto &p : holder_) {
|
|
|
|
delete[] p;
|
|
|
|
}
|
|
|
|
holder_.clear();
|
|
|
|
}
|
|
|
|
static MemoryHold &Get()
|
|
|
|
{
|
|
|
|
static MemoryHold instance;
|
|
|
|
return instance;
|
|
|
|
}
|
2021-12-24 08:46:38 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<char *> holder_;
|
2021-12-29 14:26:17 +00:00
|
|
|
};
|
2021-12-24 08:46:38 +00:00
|
|
|
|
|
|
|
std::string StringReplace(std::string source, const std::string &from, const std::string &to);
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
std::string VectorToString(const std::vector<T> &items)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_same<T, std::vector<std::string>>::value) {
|
|
|
|
std::vector<std::string> stringItems;
|
|
|
|
for (auto item : items) {
|
|
|
|
stringItems.push_back("[" + VectorToString(item) + "]");
|
|
|
|
}
|
|
|
|
return VectorToString(stringItems);
|
|
|
|
} else {
|
|
|
|
std::string itemsString;
|
|
|
|
const std::string split = ",";
|
|
|
|
for (auto item : items) {
|
|
|
|
if (!itemsString.empty())
|
|
|
|
itemsString.append(split);
|
|
|
|
if constexpr (std::is_same<T, std::string>::value) {
|
|
|
|
itemsString.append(item);
|
|
|
|
} else {
|
|
|
|
itemsString.append(std::to_string(item));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (itemsString.empty())
|
|
|
|
itemsString.append("<empty>");
|
|
|
|
return itemsString;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string BufferToHexString(const std::vector<unsigned char> &vec);
|
|
|
|
std::string BufferToHexString(const unsigned char buf[], size_t size);
|
|
|
|
void HexDump(const void *buf, size_t size, size_t max_size = 0);
|
|
|
|
|
|
|
|
std::string &StringTrim(std::string &s);
|
|
|
|
|
2024-08-23 03:17:18 +00:00
|
|
|
std::vector<std::string> StringSplit(std::string source, const std::string &split = ",");
|
2021-12-24 08:46:38 +00:00
|
|
|
|
|
|
|
size_t SubStringCount(const std::string &source, const std::string &sub);
|
|
|
|
|
|
|
|
bool StringStartsWith(const std::string &string, const std::string &with);
|
|
|
|
|
|
|
|
bool StringEndsWith(const std::string &string, const std::string &with);
|
|
|
|
|
2021-12-29 14:26:17 +00:00
|
|
|
bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName);
|
2021-12-24 08:46:38 +00:00
|
|
|
|
|
|
|
std::vector<pid_t> GetSubthreadIDs(const pid_t pid);
|
|
|
|
|
|
|
|
bool IsDigits(const std::string &str);
|
|
|
|
|
|
|
|
bool IsHexDigits(const std::string &str);
|
|
|
|
|
|
|
|
constexpr const int COMPRESS_READ_BUF_SIZE = 4096;
|
|
|
|
// compress specified dataFile into gzip file
|
|
|
|
bool CompressFile(const std::string &dataFile, const std::string &destFile);
|
|
|
|
// uncompress specified gzip file into dataFile
|
|
|
|
bool UncompressFile(const std::string &gzipFile, const std::string &dataFile);
|
|
|
|
|
|
|
|
template<typename... VA>
|
|
|
|
std::string StringPrintf(const char *stringFormat, VA... args)
|
|
|
|
{
|
|
|
|
// check howmany bytes we need
|
|
|
|
char bytes[DEFAULT_STRING_BUF_SIZE];
|
|
|
|
bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0';
|
|
|
|
|
|
|
|
if (stringFormat == nullptr) {
|
|
|
|
return EMPTY_STRING;
|
|
|
|
}
|
|
|
|
|
|
|
|
// print it to bytes
|
2022-01-19 06:11:17 +00:00
|
|
|
if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat,
|
2021-12-24 08:46:38 +00:00
|
|
|
args...) < 0) {
|
|
|
|
return EMPTY_STRING;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make a string return
|
|
|
|
return std::string(bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
// path check
|
|
|
|
std::vector<std::string> GetEntriesInDir(const std::string &basePath);
|
|
|
|
|
|
|
|
std::vector<std::string> GetSubDirs(const std::string &basePath);
|
2023-06-06 09:22:53 +00:00
|
|
|
std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map);
|
2021-12-24 08:46:38 +00:00
|
|
|
|
|
|
|
bool IsDir(const std::string &path);
|
|
|
|
|
|
|
|
bool IsPath(const std::string &fileName);
|
|
|
|
|
2023-05-24 06:23:29 +00:00
|
|
|
bool LittleMemory();
|
|
|
|
|
2023-12-12 07:07:54 +00:00
|
|
|
#if defined(is_mingw) && is_mingw
|
2021-12-24 08:46:38 +00:00
|
|
|
const char PATH_SEPARATOR = '\\';
|
|
|
|
#else
|
|
|
|
const char PATH_SEPARATOR = '/';
|
|
|
|
#endif
|
|
|
|
const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
|
|
|
|
|
|
|
|
std::string PlatformPathConvert(const std::string &path);
|
|
|
|
|
|
|
|
// attribute
|
|
|
|
#define PACKED __attribute__((packed))
|
|
|
|
|
|
|
|
// data align
|
|
|
|
|
|
|
|
// some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu
|
|
|
|
#define HIPERF_BUF_ALIGN alignas(64)
|
|
|
|
|
2022-03-28 09:22:10 +00:00
|
|
|
#define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1)))
|
|
|
|
|
2021-12-24 08:46:38 +00:00
|
|
|
uint32_t RoundUp(uint32_t x, const int align);
|
|
|
|
|
2022-03-09 09:52:17 +00:00
|
|
|
// data convert function
|
2021-12-24 08:46:38 +00:00
|
|
|
template<class T>
|
2022-03-09 09:52:17 +00:00
|
|
|
std::string ToHex(const T &source, int size = sizeof(T), bool prefix = false)
|
2021-12-24 08:46:38 +00:00
|
|
|
{
|
|
|
|
std::stringstream ss;
|
2022-03-09 09:52:17 +00:00
|
|
|
if (prefix) {
|
2021-12-24 08:46:38 +00:00
|
|
|
ss << "0x";
|
|
|
|
}
|
|
|
|
ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source;
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
// data move and copy
|
|
|
|
template<class S, class T>
|
|
|
|
size_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)
|
|
|
|
{
|
|
|
|
if (size == 0) {
|
|
|
|
size = sizeof(T);
|
|
|
|
}
|
|
|
|
if (memcpy_s(dest, size, buffer, size) != EOK) {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
buffer = buffer + size;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// file read write
|
|
|
|
bool ReadIntFromProcFile(const std::string &path, int &value);
|
|
|
|
bool WriteIntToProcFile(const std::string &path, int value);
|
|
|
|
std::string ReadFileToString(const std::string &fileName);
|
|
|
|
bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
|
|
|
|
bool WriteStringToFile(const std::string &fileName, const std::string &value);
|
|
|
|
|
|
|
|
// stdout
|
|
|
|
class StdoutRecord {
|
|
|
|
public:
|
|
|
|
~StdoutRecord()
|
|
|
|
{
|
|
|
|
Stop(); // stdout need restore
|
|
|
|
}
|
|
|
|
StdoutRecord(const std::string &tempFile = EMPTY_STRING,
|
|
|
|
const std::string &mode = EMPTY_STRING);
|
|
|
|
|
|
|
|
bool Start();
|
|
|
|
std::string Stop();
|
|
|
|
|
|
|
|
private:
|
|
|
|
OHOS::UniqueFd stdoutFile_; // back and restore stdout
|
|
|
|
std::FILE *recordFile_ = nullptr; // save the output
|
|
|
|
bool stop_ = true;
|
|
|
|
std::string content_ = EMPTY_STRING;
|
|
|
|
};
|
|
|
|
|
|
|
|
// misc
|
|
|
|
template<class T>
|
|
|
|
float Percentage(const T &a, const T &b)
|
|
|
|
{
|
2024-07-15 07:25:58 +00:00
|
|
|
if (b == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
2021-12-24 08:46:38 +00:00
|
|
|
return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsRoot();
|
2023-04-14 03:50:56 +00:00
|
|
|
bool IsBeta();
|
|
|
|
bool IsAllowProfilingUid();
|
2024-04-02 03:22:03 +00:00
|
|
|
bool IsHiviewCall();
|
2022-02-18 07:42:09 +00:00
|
|
|
bool PowerOfTwo(uint64_t n);
|
2024-11-14 11:02:51 +00:00
|
|
|
bool IsNumberic(const std::string& str);
|
2021-12-24 08:46:38 +00:00
|
|
|
|
2024-06-20 06:37:44 +00:00
|
|
|
const std::string HMKERNEL = "HongMeng";
|
2023-10-29 08:38:55 +00:00
|
|
|
|
2024-05-08 03:21:09 +00:00
|
|
|
#define PRINT_INDENT(indent, format, ...) \
|
2021-12-24 08:46:38 +00:00
|
|
|
if (indent >= 0) { \
|
2024-05-08 03:21:09 +00:00
|
|
|
if (g_outputDump == nullptr) { \
|
2023-05-31 10:13:59 +00:00
|
|
|
printf("%*s" format, (indent)*2, "", ##__VA_ARGS__); \
|
|
|
|
} else { \
|
2024-05-08 03:21:09 +00:00
|
|
|
fprintf(g_outputDump, "%*s" format, (indent)*2, "", ##__VA_ARGS__); \
|
2023-05-31 10:13:59 +00:00
|
|
|
} \
|
2021-12-24 08:46:38 +00:00
|
|
|
} else { \
|
|
|
|
HLOGV("%s" format, "", ##__VA_ARGS__); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef MMAP_FAILED
|
|
|
|
#define MMAP_FAILED reinterpret_cast<void *>(-1)
|
|
|
|
#endif
|
|
|
|
#ifndef MAP_FAILED
|
|
|
|
#define MAP_FAILED MMAP_FAILED
|
|
|
|
#endif
|
2023-05-31 10:13:59 +00:00
|
|
|
pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
|
|
|
|
const uint64_t waitAppTimeOut);
|
2023-09-05 09:53:57 +00:00
|
|
|
bool IsRestarted(const std::string &appPackage);
|
|
|
|
void CollectPidsByAppname(std::set<pid_t> &pids, const std::string &appPackage);
|
2023-04-24 12:32:26 +00:00
|
|
|
bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs);
|
2024-11-01 07:01:44 +00:00
|
|
|
bool IsExistDebugByApp(const std::string& bundleName, std::string& err);
|
|
|
|
bool IsExistDebugByPid(const std::vector<pid_t> &pids, std::string& err);
|
2023-04-14 03:50:56 +00:00
|
|
|
bool IsSupportNonDebuggableApp();
|
|
|
|
const std::string GetUserType();
|
2024-08-27 08:08:03 +00:00
|
|
|
bool GetDeveloperMode();
|
2024-02-28 01:52:41 +00:00
|
|
|
bool IsArkJsFile(const std::string& filepath);
|
2023-02-01 13:18:57 +00:00
|
|
|
std::string GetProcessName(int pid);
|
2023-11-27 14:07:15 +00:00
|
|
|
bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
|
2024-02-05 08:39:16 +00:00
|
|
|
bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
|
2024-01-02 12:36:00 +00:00
|
|
|
|
|
|
|
template <typename Func>
|
|
|
|
class ScopeGuard {
|
|
|
|
public:
|
2024-05-08 03:21:09 +00:00
|
|
|
explicit ScopeGuard(Func&& fn)
|
2024-01-03 01:11:34 +00:00
|
|
|
: fn_(fn) {}
|
|
|
|
~ScopeGuard()
|
|
|
|
{
|
2024-01-02 12:36:00 +00:00
|
|
|
fn_();
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
Func fn_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ScopeGuardOnExit {};
|
|
|
|
template <typename Func>
|
2024-01-03 01:11:34 +00:00
|
|
|
static inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func&& fn)
|
|
|
|
{
|
2024-01-02 12:36:00 +00:00
|
|
|
return ScopeGuard<Func>(std::forward<Func>(fn));
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ON_SCOPE_EXIT \
|
|
|
|
auto __onGuardExit__ = ScopeGuardOnExit{} + [&]
|
2021-12-24 08:46:38 +00:00
|
|
|
} // namespace HiPerf
|
|
|
|
} // namespace Developtools
|
|
|
|
} // namespace OHOS
|
2022-03-25 03:49:41 +00:00
|
|
|
#endif // HIPERF_UTILITIES_H_
|