• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "utilities.h"
16 #include <zlib.h>
17 #include <thread>
18 #if defined(CONFIG_HAS_SYSPARA) && defined(is_ohos) && is_ohos
19 #include <parameters.h>
20 #endif
21 #if defined(is_mingw) && is_mingw
22 #include <io.h>
23 #endif
24 #if defined(is_ohos) && is_ohos
25 #include "application_info.h"
26 #include "bundle_mgr_proxy.h"
27 #include "iservice_registry.h"
28 #include "system_ability_definition.h"
29 using namespace OHOS;
30 using namespace OHOS::AppExecFwk;
31 #endif
32 
33 using namespace std::chrono;
34 namespace OHOS {
35 namespace Developtools {
36 namespace HiPerf {
37 
HoldStringView(std::string_view view)38 const char *MemoryHold::HoldStringView(std::string_view view)
39 {
40     if (view.size() == 0) {
41         return "";
42     }
43     try {
44         // for null end
45         char *p = new (std::nothrow) char[view.size() + 1];
46         if (p == nullptr) {
47             return "";
48         }
49         p[view.size()] = '\0';
50         std::copy(view.data(), view.data() + view.size(), p);
51         holder_.emplace_back(p);
52         return p;
53     } catch (...) {
54         return "";
55     }
56     return "";
57 }
58 
CanonicalizeSpecPath(const char * src)59 std::string CanonicalizeSpecPath(const char* src)
60 {
61     if (src == nullptr) {
62         fprintf(stderr, "Error: CanonicalizeSpecPath failed");
63         return "";
64     } else if (strlen(src) >= PATH_MAX) {
65         fprintf(stderr, "Error: CanonicalizeSpecPath %s failed", src);
66         return "";
67     }
68     char resolvedPath[PATH_MAX] = { 0 };
69 #if defined(_WIN32)
70     if (!_fullpath(resolvedPath, src, PATH_MAX)) {
71         fprintf(stderr, "Error: _fullpath %s failed", src);
72         return "";
73     }
74 #else
75     if (access(src, F_OK) == 0) {
76         if (strstr(src, "/proc/") == src && strstr(src, "/data/storage") != nullptr) { // for sandbox
77             (void)strncpy_s(resolvedPath, sizeof(resolvedPath), src, strlen(src));
78         } else if (realpath(src, resolvedPath) == nullptr) {
79             fprintf(stderr, "Error: realpath %s failed", src);
80             return "";
81         }
82     } else {
83         std::string fileName(src);
84         if (fileName.find("..") == std::string::npos) {
85             if (sprintf_s(resolvedPath, PATH_MAX, "%s", src) == -1) {
86                 fprintf(stderr, "Error: sprintf_s %s failed", src);
87                 return "";
88             }
89         } else {
90             fprintf(stderr, "Error: find .. %s failed", src);
91             return "";
92         }
93     }
94 #endif
95     std::string res(resolvedPath);
96     return res;
97 }
98 
RoundUp(uint32_t x,const int align)99 uint32_t RoundUp(uint32_t x, const int align)
100 {
101     return (((x) + (align) - 1) / (align)) * (align);
102 }
103 
StringReplace(std::string source,const std::string & from,const std::string & to)104 std::string StringReplace(std::string source, const std::string &from, const std::string &to)
105 {
106     size_t pos = 0;
107     std::string result;
108     // find
109     while ((pos = source.find(from)) != std::string::npos) {
110         // replace
111         result.append(source.substr(0, pos) + to);
112         source.erase(0, pos + from.length());
113     }
114     // add last token
115     result.append(source);
116     return result;
117 }
118 
SubStringCount(const std::string & source,const std::string & sub)119 size_t SubStringCount(const std::string &source, const std::string &sub)
120 {
121     size_t count(0);
122     size_t pos(0);
123     if (sub.empty()) {
124         return source.size();
125     }
126     while ((pos = source.find(sub, pos)) != std::string::npos) {
127         pos += sub.size();
128         count++;
129     }
130     return count;
131 }
132 
StringSplit(std::string source,const std::string split)133 std::vector<std::string> StringSplit(std::string source, const std::string split)
134 {
135     std::vector<std::string> result;
136 
137     // find
138     if (!split.empty()) {
139         size_t pos = 0;
140         while ((pos = source.find(split)) != std::string::npos) {
141             // split
142             std::string token = source.substr(0, pos);
143             if (!token.empty()) {
144                 result.push_back(token);
145             }
146             source.erase(0, pos + split.length());
147         }
148     }
149     // add last token
150     if (!source.empty()) {
151         result.push_back(source);
152     }
153     return result;
154 }
StdoutRecord(const std::string & tempFile,const std::string & mode)155 StdoutRecord::StdoutRecord(const std::string &tempFile, const std::string &mode)
156 {
157     if (!tempFile.empty()) {
158         std::string resolvedPath = CanonicalizeSpecPath(tempFile.c_str());
159         recordFile_ = fopen(resolvedPath.c_str(), mode.c_str());
160         if (recordFile_ == nullptr) {
161             HLOGE("tmpfile create failed '%s' with mode '%s'", tempFile.c_str(), mode.c_str());
162         } else {
163             // auto start it
164             Start();
165         }
166     }
167 }
Start()168 bool StdoutRecord::Start()
169 {
170     content_ = EMPTY_STRING;
171     fflush(stdout);
172 
173     // we will save output here
174     if (recordFile_ == nullptr) {
175         recordFile_ = std::tmpfile();
176     }
177     if (recordFile_ == nullptr) {
178         // try second way
179         std::string fileName = "/data/local/tmp/temp.stdout";
180         std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str());
181         recordFile_ = fopen(resolvedPath.c_str(), "w+");
182         if (recordFile_ == nullptr) {
183             HLOGF("tmpfile create failed '%s'", fileName.c_str());
184             return false;
185         }
186     }
187 
188     // we save the stdout
189     stdoutFile_ = OHOS::UniqueFd(dup(STDOUT_FILENO));
190     if (stdoutFile_ == -1) {
191         HLOGF("std dup failed");
192         return false;
193     }
194 
195     // setup temp file as stdout
196     if (dup2(fileno(recordFile_), STDOUT_FILENO) != -1) {
197         stop_ = false;
198         return true;
199     } else {
200         HLOGF("std dup2 failed");
201         return false;
202     }
203 }
204 
Stop()205 std::string StdoutRecord::Stop()
206 {
207     if (stop_)
208         return content_;
209     fflush(stdout);
210     // restore fd
211     dup2(stdoutFile_, STDOUT_FILENO);
212 
213     // return file content
214     if (recordFile_ != nullptr) {
215         const long fileLength = lseek(fileno(recordFile_), 0, SEEK_END);
216         content_.resize(fileLength);
217         lseek(fileno(recordFile_), 0, SEEK_SET);
218         const long len = read(fileno(recordFile_), content_.data(), fileLength);
219         std::fclose(recordFile_);
220         recordFile_ = nullptr;
221         if (len < 0) {
222             HLOGE("tmp file read failed (try read %ld)", fileLength);
223         } else if (len < fileLength) {
224             HLOGE("not all the data is read, lost %ld/%ld bytes", fileLength - len, fileLength);
225         }
226     } else {
227         HLOGE("recordFile_ is nullptr");
228     }
229     stop_ = true;
230     return content_;
231 }
232 
IsDigits(const std::string & str)233 bool IsDigits(const std::string &str)
234 {
235     if (str.empty()) {
236         return false;
237     } else {
238         return std::all_of(str.begin(), str.end(), ::isdigit);
239     }
240 }
241 
IsHexDigits(const std::string & str)242 bool IsHexDigits(const std::string &str)
243 {
244     if (str.empty()) {
245         return false;
246     }
247     const std::string prefix {"0x"};
248     std::string effectStr {str};
249     if (prefix.compare(0, prefix.size(), effectStr.substr(0, prefix.size())) == 0) {
250         effectStr = effectStr.substr(prefix.size(), effectStr.size() - prefix.size());
251     }
252     if (effectStr.empty()) {
253         return false;
254     }
255     std::size_t start {0};
256     for (; start < effectStr.size(); ++start) {
257         if (effectStr[start] == '0') {
258             continue;
259         }
260         break;
261     }
262     if (start == effectStr.size()) {
263         effectStr = "0";
264     }
265     return std::all_of(effectStr.begin(), effectStr.end(), ::isxdigit);
266 }
267 
IsDir(const std::string & path)268 bool IsDir(const std::string &path)
269 {
270     struct stat st;
271     if (stat(path.c_str(), &st) == 0) {
272         return S_ISDIR(st.st_mode);
273     }
274     return false;
275 }
276 
IsPath(const std::string & fileName)277 bool IsPath(const std::string &fileName)
278 {
279     HLOG_ASSERT(!fileName.empty());
280     if (fileName[0] == PATH_SEPARATOR) {
281         return true;
282     }
283     const int prefixPathLen = 2;
284     if (fileName.substr(0, prefixPathLen) == "./") {
285         return true;
286     }
287     return false;
288 }
289 
PlatformPathConvert(const std::string & path)290 std::string PlatformPathConvert(const std::string &path)
291 {
292 #if defined(is_mingw) && is_mingw
293     return StringReplace(path, "/", "\\");
294 #else
295     return path;
296 #endif
297 }
298 
ReadFileToString(const std::string & fileName)299 std::string ReadFileToString(const std::string &fileName)
300 {
301     std::ifstream inputString(fileName, std::ios::in);
302     if (!inputString or !inputString.is_open()) {
303         return EMPTY_STRING;
304     }
305     std::istreambuf_iterator<char> firstIt = {inputString};
306     std::istreambuf_iterator<char> lastIt = {};
307 
308     std::string content(firstIt, lastIt);
309     return content;
310 }
311 
ReadFileToString(const std::string & fileName,std::string & fileData,size_t fileSize)312 bool ReadFileToString(const std::string &fileName, std::string &fileData, size_t fileSize)
313 {
314     fileData.clear();
315     std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str());
316     OHOS::UniqueFd fd(open(resolvedPath.c_str(), O_RDONLY | O_BINARY));
317     if (fileSize == 0) {
318         struct stat fileStat;
319         if (fstat(fd.Get(), &fileStat) != -1 && fileStat.st_size > 0) {
320             fileData.reserve(fileStat.st_size);
321         }
322     } else {
323         fileData.reserve(fileSize);
324     }
325 
326     char buf[BUFSIZ] __attribute__((__uninitialized__));
327     ssize_t readSize;
328     while ((readSize = read(fd.Get(), &buf[0], sizeof(buf))) > 0) {
329         fileData.append(buf, readSize);
330     }
331     return (readSize == 0) ? true : false;
332 }
333 
WriteStringToFile(const std::string & fileName,const std::string & value)334 bool WriteStringToFile(const std::string &fileName, const std::string &value)
335 {
336     std::ofstream output(fileName, std::ios::out);
337     if (!output) {
338         return false;
339     }
340     output << value;
341 
342     return output.good();
343 }
344 
IsRoot()345 bool IsRoot()
346 {
347 #if is_linux || is_ohos
348     static bool isRoot = (getuid() == 0);
349     return isRoot;
350 #else
351     return true;
352 #endif
353 }
354 
PowerOfTwo(uint64_t n)355 bool PowerOfTwo(uint64_t n)
356 {
357     return n && (!(n & (n - 1)));
358 }
359 
ReadIntFromProcFile(const std::string & path,int & value)360 bool ReadIntFromProcFile(const std::string &path, int &value)
361 {
362     std::string s = ReadFileToString(path);
363     if (s.empty()) {
364         return false;
365     }
366     value = std::stoi(s);
367     return true;
368 }
369 
WriteIntToProcFile(const std::string & path,int value)370 bool WriteIntToProcFile(const std::string &path, int value)
371 {
372     std::string s = std::to_string(value);
373 
374     return WriteStringToFile(path, s);
375 }
376 
377 // compress specified dataFile into gzip file
CompressFile(const std::string & dataFile,const std::string & destFile)378 bool CompressFile(const std::string &dataFile, const std::string &destFile)
379 {
380     std::string resolvedPath = CanonicalizeSpecPath(dataFile.c_str());
381     FILE *fp = fopen(resolvedPath.c_str(), "rb");
382     if (fp == nullptr) {
383         HLOGE("Fail to open data file %s", dataFile.c_str());
384         perror("Fail to fopen(rb)");
385         return false;
386     }
387 
388     std::unique_ptr<gzFile_s, decltype(&gzclose)> fgz(gzopen(destFile.c_str(), "wb"), gzclose);
389     if (fgz == nullptr) {
390         HLOGE("Fail to call gzopen(%s)", destFile.c_str());
391         fclose(fp);
392         return false;
393     }
394 
395     std::vector<char> buf(COMPRESS_READ_BUF_SIZE);
396     size_t len = 0;
397     while ((len = fread(buf.data(), sizeof(uint8_t), buf.size(), fp))) {
398         if (gzwrite(fgz.get(), buf.data(), len) == 0) {
399             HLOGE("Fail to call gzwrite for %zu bytes", len);
400             fclose(fp);
401             return false;
402         }
403     }
404     if (!feof(fp)) {
405         if (ferror(fp) != 0) {
406             HLOGE("ferror return err");
407             fclose(fp);
408             return false;
409         }
410     }
411     if (fclose(fp) < 0) {
412         return false;
413     }
414     return true;
415 }
416 
417 // uncompress specified gzip file into dataFile
UncompressFile(const std::string & gzipFile,const std::string & dataFile)418 bool UncompressFile(const std::string &gzipFile, const std::string &dataFile)
419 {
420     std::string resolvedPath = CanonicalizeSpecPath(dataFile.c_str());
421     FILE *fp = fopen(resolvedPath.c_str(), "wb");
422     if (fp == nullptr) {
423         HLOGE("Fail to open data file %s", dataFile.c_str());
424         perror("Fail to fopen(rb)");
425         return false;
426     }
427     std::unique_ptr<gzFile_s, decltype(&gzclose)> fgz(gzopen(gzipFile.c_str(), "rb"), gzclose);
428     if (fgz == nullptr) {
429         HLOGE("Fail to call gzopen(%s)", gzipFile.c_str());
430         fclose(fp);
431         return false;
432     }
433 
434     std::vector<char> buf(COMPRESS_READ_BUF_SIZE);
435     z_size_t len = 0;
436     while ((len = gzfread(buf.data(), sizeof(uint8_t), buf.size(), fgz.get()))) {
437         if (len != fwrite(buf.data(), sizeof(uint8_t), len, fp)) {
438             HLOGE("Fail to call fwrite for %zu bytes", len);
439             fclose(fp);
440             return false;
441         }
442     }
443     if (!gzeof(fgz.get())) {
444         int rc = 0;
445         const char *err = gzerror(fgz.get(), &rc);
446         if (rc != Z_OK) {
447             HLOGE("gzfread return %d:%s", rc, err);
448             fclose(fp);
449             return false;
450         }
451     }
452     if (fclose(fp) < 0) {
453         return false;
454     }
455     return true;
456 }
457 
StringTrim(std::string & string)458 std::string &StringTrim(std::string &string)
459 {
460     if (!string.empty()) {
461         string.erase(0, string.find_first_not_of(" "));
462         string.erase(string.find_last_not_of(" ") + 1);
463     }
464     return string;
465 }
466 
GetEntriesInDir(const std::string & basePath)467 std::vector<std::string> GetEntriesInDir(const std::string &basePath)
468 {
469     std::vector<std::string> result;
470     std::string resolvedPath = CanonicalizeSpecPath(basePath.c_str());
471     if (resolvedPath.empty()) {
472         return result;
473     }
474     DIR *dir = opendir(resolvedPath.c_str());
475     if (dir == nullptr) {
476         return result;
477     }
478     dirent *entry;
479     while ((entry = readdir(dir)) != nullptr) {
480         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
481             continue;
482         }
483         result.push_back(entry->d_name);
484     }
485     closedir(dir);
486     return result;
487 }
488 
GetSubDirs(const std::string & basePath)489 std::vector<std::string> GetSubDirs(const std::string &basePath)
490 {
491     std::vector<std::string> entries = GetEntriesInDir(basePath);
492     std::vector<std::string> result = {};
493     for (std::size_t index = 0; index < entries.size(); ++index) {
494         if (IsDir(basePath + "/" + entries[index])) {
495             result.push_back(std::move(entries[index]));
496         }
497     }
498     return result;
499 }
500 
IsSameCommand(const std::string & cmdLine,const std::string & cmdName)501 bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName)
502 {
503     std::vector<std::string> cmdpaths = StringSplit(cmdLine, "/");
504     if (!cmdpaths.empty()) {
505         if (strcmp(cmdpaths.back().c_str(), cmdName.c_str()) == 0) {
506             return true;
507         }
508     }
509     return false;
510 }
511 
GetSubthreadIDs(const pid_t pid)512 std::vector<pid_t> GetSubthreadIDs(const pid_t pid)
513 {
514     std::string path {"/proc/"};
515     path += std::to_string(pid);
516     path += "/task/";
517     auto tids = GetSubDirs(path);
518     std::vector<pid_t> res {};
519     for (auto tidStr : tids) {
520         pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr));
521         if (tid == pid) {
522             continue;
523         }
524         res.push_back(tid);
525     }
526     return res;
527 }
528 
GetSubthreadIDs(const pid_t pid,std::map<pid_t,ThreadInfos> & thread_map)529 std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map)
530 {
531     std::string path {"/proc/"};
532     path += std::to_string(pid);
533     path += "/task/";
534     auto tids = GetSubDirs(path);
535     std::vector<pid_t> res{};
536     for (auto tidStr : tids) {
537         ThreadInfos info;
538         pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr));
539         info.tid = tid;
540         info.pid = pid;
541         thread_map[tid] = info;
542         res.push_back(tid);
543     }
544     return res;
545 }
546 
StringStartsWith(const std::string & string,const std::string & with)547 bool StringStartsWith(const std::string &string, const std::string &with)
548 {
549     return string.find(with) == 0;
550 }
551 
StringEndsWith(const std::string & string,const std::string & with)552 bool StringEndsWith(const std::string &string, const std::string &with)
553 {
554     if (string.empty()) {
555         // empty string only end with empty string
556         if (with.empty()) {
557             return true;
558         } else {
559             return false;
560         }
561     }
562     return string.rfind(with) == (string.length() - with.length());
563 }
564 
HexDump(const void * buf,size_t size,size_t maxSize)565 void HexDump(const void *buf, size_t size, size_t maxSize)
566 {
567     const unsigned char *byteBuf = static_cast<const unsigned char *>(buf);
568     const size_t dumpByteEachLine = 8;
569     size_t outputBytes = 0;
570     if (!maxSize) {
571         outputBytes = size;
572     } else {
573         outputBytes = std::min(size, maxSize);
574     }
575 
576     for (size_t i = 0; i <= outputBytes; i += dumpByteEachLine) {
577         HLOGM(" %02zu: %s ", i, BufferToHexString(byteBuf, dumpByteEachLine).c_str());
578         byteBuf += dumpByteEachLine;
579     }
580 }
581 
BufferToHexString(const std::vector<unsigned char> & vec)582 std::string BufferToHexString(const std::vector<unsigned char> &vec)
583 {
584     return BufferToHexString(vec.data(), vec.size());
585 }
586 
BufferToHexString(const unsigned char buf[],size_t size)587 std::string BufferToHexString(const unsigned char buf[], size_t size)
588 {
589     std::stringstream ss;
590     ss << size << ":";
591     for (size_t i = 0; i < size; i++) {
592         ss << " 0x" << std::setfill('0') << std::setw(BYTE_PRINT_WIDTH) << std::hex
593            << (unsigned short)buf[i];
594     }
595     return ss.str();
596 }
597 
GetAppPackagePid(const std::string & appPackage,const pid_t oldPid,const int checkAppMs,const uint64_t waitAppTimeOut)598 pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
599                        const uint64_t waitAppTimeOut)
600 {
601     pid_t res {-1};
602     const std::string basePath {"/proc/"};
603     const auto startTime = steady_clock::now();
604     const auto endTime = startTime + std::chrono::seconds(waitAppTimeOut);
605     do {
606         std::vector<std::string> subDirs = GetSubDirs(basePath);
607         for (const auto &subDir : subDirs) {
608             if (!IsDigits(subDir)) {
609                 continue;
610             }
611             std::string fileName {basePath + subDir};
612             fileName += "/cmdline";
613             if (!IsNeedCheckSamePid(fileName, appPackage, subDir, res, oldPid)) {
614                 return res;
615             }
616         }
617         std::this_thread::sleep_for(milliseconds(checkAppMs));
618     } while (steady_clock::now() < endTime);
619 
620     return res;
621 }
622 
IsNeedCheckSamePid(const std::string & fileName,const std::string & appPackage,const std::string & subDir,pid_t & res,const pid_t oldPid)623 bool IsNeedCheckSamePid(const std::string &fileName, const std::string &appPackage, const std::string &subDir,
624                         pid_t &res, const pid_t oldPid)
625 {
626     if (IsSameCommand(ReadFileToString(fileName), appPackage)) {
627         res = std::stoul(subDir, nullptr);
628         if (res == oldPid) {
629             res = -1;
630             return true;
631         }
632         if (res >= 0) {
633             HLOGD("[GetAppPackagePid]: get appid for %s is %d", appPackage.c_str(), res);
634             return false;
635         }
636     }
637     return true;
638 }
639 
CheckAppIsRunning(std::vector<pid_t> & selectPids,const std::string & appPackage,int checkAppMs)640 bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs)
641 {
642     if (!appPackage.empty()) {
643         pid_t appPid = GetAppPackagePid(appPackage, -1, checkAppMs, waitAppRunCheckTimeOut);
644         if (appPid <= 0) {
645             printf("app %s not running\n", appPackage.c_str());
646             return false;
647         }
648         HLOGD("[CheckAppIsRunning] get appPid %d for app %s\n", appPid, appPackage.c_str());
649         selectPids.push_back(appPid);
650     }
651     return true;
652 }
653 
IsExistDebugByApp(const std::string & bundleName)654 bool IsExistDebugByApp(const std::string& bundleName)
655 {
656     if (!IsSupportNonDebuggableApp() && !bundleName.empty() && !IsDebugableApp(bundleName)) {
657         HLOGE("--app option only support debug aplication.");
658         printf("--app option only support debug aplication\n");
659         return false;
660     }
661     return true;
662 }
663 
IsExistDebugByPid(const std::vector<pid_t> pids)664 bool IsExistDebugByPid(const std::vector<pid_t> pids)
665 {
666     if (pids.empty()) {
667         HLOGE("IsExistDebugByPid: pids is empty.");
668         return true;
669     }
670     for (auto pid : pids) {
671         if (pid <= 0) {
672             printf("Invalid -p value '%d', the pid should be larger than 0\n", pid);
673             return false;
674         }
675         std::string bundleName = GetProcessName(pid);
676         if (!IsSupportNonDebuggableApp() && !IsDebugableApp(bundleName)) {
677             HLOGE("-p option only support debug aplication for %s", bundleName.c_str());
678             printf("-p option only support debug aplication\n");
679             return false;
680         }
681     }
682     return true;
683 }
684 
IsSupportNonDebuggableApp()685 bool IsSupportNonDebuggableApp()
686 {
687     // root first
688     if (IsRoot()) {
689         return true;
690     }
691     // user mode
692     if (!IsBeta()) {
693         return false;
694     }
695     // restricted aplication for beta
696     if (!IsAllowProfilingUid()) {
697         return false;
698     }
699     return true;
700 }
701 
GetUserType()702 const std::string GetUserType()
703 {
704 #if defined(is_ohos) && is_ohos
705     std::string userType = OHOS::system::GetParameter(USER_TYPE_PARAM, USER_TYPE_PARAM_GET);
706     HLOGD("GetUserType: userType is %s", userType.c_str());
707     return userType;
708 #else
709     return "";
710 #endif
711 }
712 
LittleMemory()713 bool LittleMemory()
714 {
715     std::ifstream file("/proc/meminfo");
716     std::string line;
717     while (getline(file, line)) {
718         if (line.find("MemTotal:") != std::string::npos) {
719             int memSize = stoi(line.substr(line.find(":") + 1));
720             if (memSize < (LITTLE_MEMORY_SIZE * MULTIPLE_SIZE * MULTIPLE_SIZE)) {
721                 return true;
722             }
723         }
724     }
725     return false;
726 }
727 
728 // only for domestic beta
IsBeta()729 bool IsBeta()
730 {
731     std::string userTypeRsp = GetUserType();
732     if (userTypeRsp == USER_DOMESTIC_BETA) {
733         return true;
734     }
735     // default release when usertype param is invalid
736     if (userTypeRsp.empty()) {
737         HLOGE("GetUserType is empty [%s]", userTypeRsp.c_str());
738         return true;
739     }
740     return false;
741 }
742 
IsAllowProfilingUid()743 bool IsAllowProfilingUid()
744 {
745 #if (defined(is_linux) && is_linux) || (defined(is_ohos) && is_ohos)
746     static unsigned int curUid = getuid();
747     HLOGD("curUid is %d\n", curUid);
748     if (ALLOW_UIDS.find(curUid) != ALLOW_UIDS.end()) {
749         return true;
750     }
751     return false;
752 #else
753     return false;
754 #endif
755 }
756 
GetProcessName(int pid)757 std::string GetProcessName(int pid)
758 {
759 #if defined(is_ohos) && is_ohos
760     std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
761     std::string bundleName = ReadFileToString(filePath);
762     return bundleName.substr(0, strlen(bundleName.c_str()));
763 #else
764     return "";
765 #endif
766 }
767 
IsDebugableApp(const std::string & bundleName)768 bool IsDebugableApp(const std::string& bundleName)
769 {
770 #if defined(is_ohos) && is_ohos
771     if (bundleName.empty()) {
772         printf("bundleName is empty!\n");
773         return false;
774     }
775     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
776     if (sam == nullptr) {
777         printf("GetSystemAbilityManager failed!\n");
778         return false;
779     }
780     sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
781     if (remoteObject == nullptr) {
782         printf("Get BundleMgr SA failed!\n");
783         return false;
784     }
785     sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
786     if (proxy == nullptr) {
787         printf("iface_cast failed!\n");
788         return false;
789     }
790 
791     int uid = proxy->GetUidByDebugBundleName(bundleName, Constants::ANY_USERID);
792     if (uid < 0) {
793         HLOGE("Get application info failed, bundleName:%s, uid is %d.", bundleName.c_str(), uid);
794         return false;
795     }
796     return true;
797 #else
798     return false;
799 #endif
800 }
801 
AdaptSandboxPath(std::string filePath,int pid)802 std::string AdaptSandboxPath(std::string filePath, int pid)
803 {
804     if (filePath.find("/data/storage") == 0 && access(filePath.c_str(), F_OK) != 0) {
805         filePath = "/proc/" + std::to_string(pid) + "/root" + filePath;
806     }
807     return filePath;
808 }
809 
810 } // namespace HiPerf
811 } // namespace Developtools
812 } // namespace OHOS
813 
814 // this will also used for libunwind head (out of namespace)
815 #if defined(is_mingw) && is_mingw
816 using namespace OHOS::Developtools::HiPerf;
GetLastErrorString()817 std::string GetLastErrorString()
818 {
819     LPVOID lpMsgBuf;
820     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
821                       FORMAT_MESSAGE_IGNORE_INSERTS,
822                   NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL);
823     std::string error((LPTSTR)lpMsgBuf);
824     LocalFree(lpMsgBuf);
825     return error;
826 }
827 
mmap(void * addr,size_t length,int prot,int flags,int fd,size_t offset)828 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset)
829 {
830     HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
831     if (FileHandle == INVALID_HANDLE_VALUE) {
832         return MMAP_FAILED;
833     }
834 
835     HLOGV("fd is %d", fd);
836 
837     HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
838     if (FileMappingHandle == nullptr) {
839         HLOGE("CreateFileMappingW %zu Failed with %ld:%s", length, GetLastError(),
840               GetLastErrorString().c_str());
841         return MMAP_FAILED;
842     }
843 
844     void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
845     if (mapAddr == nullptr) {
846         HLOGE("MapViewOfFile %zu Failed with %ld:%s", length, GetLastError(),
847               GetLastErrorString().c_str());
848         return MMAP_FAILED;
849     }
850 
851     // Close all the handles except for the view. It will keep the other handles
852     // alive.
853     ::CloseHandle(FileMappingHandle);
854     return mapAddr;
855 }
856 
munmap(void * addr,size_t)857 int munmap(void *addr, size_t)
858 {
859     /*
860         On success, munmap() returns 0.  On failure, it returns -1, and
861         errno is set to indicate the error (probably to EINVAL).
862 
863         UnmapViewOfFile function (memoryapi.h)
864 
865         If the function succeeds, the return value is nonzero.
866         If the function fails, the return value is zero. To get extended error information, call
867     GetLastError.
868     */
869     return !UnmapViewOfFile(addr);
870 }
871 #endif
872