• 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     DIR *dir = opendir(basePath.c_str());
471     if (dir == nullptr) {
472         return result;
473     }
474     dirent *entry;
475     while ((entry = readdir(dir)) != nullptr) {
476         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
477             continue;
478         }
479         result.push_back(entry->d_name);
480     }
481     closedir(dir);
482     return result;
483 }
484 
GetSubDirs(const std::string & basePath)485 std::vector<std::string> GetSubDirs(const std::string &basePath)
486 {
487     std::vector<std::string> entries = GetEntriesInDir(basePath);
488     std::vector<std::string> result = {};
489     for (std::size_t index = 0; index < entries.size(); ++index) {
490         if (IsDir(basePath + "/" + entries[index])) {
491             result.push_back(std::move(entries[index]));
492         }
493     }
494     return result;
495 }
496 
IsSameCommand(const std::string & cmdLine,const std::string & cmdName)497 bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName)
498 {
499     std::vector<std::string> cmdpaths = StringSplit(cmdLine, "/");
500     if (!cmdpaths.empty()) {
501         if (strcmp(cmdpaths.back().c_str(), cmdName.c_str()) == 0) {
502             return true;
503         }
504     }
505     return false;
506 }
507 
GetSubthreadIDs(const pid_t pid)508 std::vector<pid_t> GetSubthreadIDs(const pid_t pid)
509 {
510     std::string path {"/proc/"};
511     path += std::to_string(pid);
512     path += "/task/";
513     auto tids = GetSubDirs(path);
514     std::vector<pid_t> res {};
515     for (auto tidStr : tids) {
516         pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr));
517         if (tid == pid) {
518             continue;
519         }
520         res.push_back(tid);
521     }
522     return res;
523 }
524 
GetSubthreadIDs(const pid_t pid,std::map<pid_t,ThreadInfos> & thread_map)525 std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map)
526 {
527     std::string path {"/proc/"};
528     path += std::to_string(pid);
529     path += "/task/";
530     auto tids = GetSubDirs(path);
531     std::vector<pid_t> res{};
532     for (auto tidStr : tids) {
533         ThreadInfos info;
534         pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr));
535         info.tid = tid;
536         info.pid = pid;
537         thread_map[tid] = info;
538         res.push_back(tid);
539     }
540     return res;
541 }
542 
StringStartsWith(const std::string & string,const std::string & with)543 bool StringStartsWith(const std::string &string, const std::string &with)
544 {
545     return string.find(with) == 0;
546 }
547 
StringEndsWith(const std::string & string,const std::string & with)548 bool StringEndsWith(const std::string &string, const std::string &with)
549 {
550     if (string.empty()) {
551         // empty string only end with empty string
552         if (with.empty()) {
553             return true;
554         } else {
555             return false;
556         }
557     }
558     return string.rfind(with) == (string.length() - with.length());
559 }
560 
HexDump(const void * buf,size_t size,size_t maxSize)561 void HexDump(const void *buf, size_t size, size_t maxSize)
562 {
563     const unsigned char *byteBuf = static_cast<const unsigned char *>(buf);
564     const size_t dumpByteEachLine = 8;
565     size_t outputBytes = 0;
566     if (!maxSize) {
567         outputBytes = size;
568     } else {
569         outputBytes = std::min(size, maxSize);
570     }
571 
572     for (size_t i = 0; i <= outputBytes; i += dumpByteEachLine) {
573         HLOGM(" %02zu: %s ", i, BufferToHexString(byteBuf, dumpByteEachLine).c_str());
574         byteBuf += dumpByteEachLine;
575     }
576 }
577 
BufferToHexString(const std::vector<unsigned char> & vec)578 std::string BufferToHexString(const std::vector<unsigned char> &vec)
579 {
580     return BufferToHexString(vec.data(), vec.size());
581 }
582 
BufferToHexString(const unsigned char buf[],size_t size)583 std::string BufferToHexString(const unsigned char buf[], size_t size)
584 {
585     std::stringstream ss;
586     ss << size << ":";
587     for (size_t i = 0; i < size; i++) {
588         ss << " 0x" << std::setfill('0') << std::setw(BYTE_PRINT_WIDTH) << std::hex
589            << (unsigned short)buf[i];
590     }
591     return ss.str();
592 }
593 
GetAppPackagePid(const std::string & appPackage,const pid_t oldPid,const int checkAppMs,const uint64_t waitAppTimeOut)594 pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
595                        const uint64_t waitAppTimeOut)
596 {
597     pid_t res {-1};
598     const std::string basePath {"/proc/"};
599     const auto startTime = steady_clock::now();
600     const auto endTime = startTime + std::chrono::seconds(waitAppTimeOut);
601     do {
602         std::vector<std::string> subDirs = GetSubDirs(basePath);
603         for (const auto &subDir : subDirs) {
604             if (!IsDigits(subDir)) {
605                 continue;
606             }
607             std::string fileName {basePath + subDir};
608             fileName += "/cmdline";
609             if (!IsNeedCheckSamePid(fileName, appPackage, subDir, res, oldPid)) {
610                 return res;
611             }
612         }
613         std::this_thread::sleep_for(milliseconds(checkAppMs));
614     } while (steady_clock::now() < endTime);
615 
616     return res;
617 }
618 
IsNeedCheckSamePid(const std::string & fileName,const std::string & appPackage,const std::string & subDir,pid_t & res,const pid_t oldPid)619 bool IsNeedCheckSamePid(const std::string &fileName, const std::string &appPackage, const std::string &subDir,
620                         pid_t &res, const pid_t oldPid)
621 {
622     if (IsSameCommand(ReadFileToString(fileName), appPackage)) {
623         res = std::stoul(subDir, nullptr);
624         if (res == oldPid) {
625             res = -1;
626             return true;
627         }
628         if (res >= 0) {
629             HLOGD("[GetAppPackagePid]: get appid for %s is %d", appPackage.c_str(), res);
630             return false;
631         }
632     }
633     return true;
634 }
635 
CheckAppIsRunning(std::vector<pid_t> & selectPids,const std::string & appPackage,int checkAppMs)636 bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs)
637 {
638     if (!appPackage.empty()) {
639         pid_t appPid = GetAppPackagePid(appPackage, -1, checkAppMs, waitAppRunCheckTimeOut);
640         if (appPid <= 0) {
641             printf("app %s not running\n", appPackage.c_str());
642             return false;
643         }
644         HLOGD("[CheckAppIsRunning] get appPid %d for app %s\n", appPid, appPackage.c_str());
645         selectPids.push_back(appPid);
646     }
647     return true;
648 }
649 
IsExistDebugByApp(const std::string & bundleName)650 bool IsExistDebugByApp(const std::string& bundleName)
651 {
652     if (!IsSupportNonDebuggableApp() && !bundleName.empty() && !IsDebugableApp(bundleName)) {
653         HLOGE("--app option only support debug aplication.");
654         printf("--app option only support debug aplication\n");
655         return false;
656     }
657     return true;
658 }
659 
IsExistDebugByPid(const std::vector<pid_t> pids)660 bool IsExistDebugByPid(const std::vector<pid_t> pids)
661 {
662     if (pids.empty()) {
663         HLOGE("IsExistDebugByPid: pids is empty.");
664         return true;
665     }
666     for (auto pid : pids) {
667         if (pid <= 0) {
668             printf("Invalid -p value '%d', the pid should be larger than 0\n", pid);
669             return false;
670         }
671         std::string bundleName = GetProcessName(pid);
672         if (!IsSupportNonDebuggableApp() && !IsDebugableApp(bundleName)) {
673             HLOGE("-p option only support debug aplication for %s", bundleName.c_str());
674             printf("-p option only support debug aplication\n");
675             return false;
676         }
677     }
678     return true;
679 }
680 
IsSupportNonDebuggableApp()681 bool IsSupportNonDebuggableApp()
682 {
683     // root first
684     if (IsRoot()) {
685         return true;
686     }
687     // user mode
688     if (!IsBeta()) {
689         return false;
690     }
691     // restricted aplication for beta
692     if (!IsAllowProfilingUid()) {
693         return false;
694     }
695     return true;
696 }
697 
GetUserType()698 const std::string GetUserType()
699 {
700 #if defined(is_ohos) && is_ohos
701     std::string userType = OHOS::system::GetParameter(USER_TYPE_PARAM, USER_TYPE_PARAM_GET);
702     HLOGD("GetUserType: userType is %s", userType.c_str());
703     return userType;
704 #else
705     return "";
706 #endif
707 }
708 
LittleMemory()709 bool LittleMemory()
710 {
711     std::ifstream file("/proc/meminfo");
712     std::string line;
713     while (getline(file, line)) {
714         if (line.find("MemTotal:") != std::string::npos) {
715             int memSize = stoi(line.substr(line.find(":") + 1));
716             if (memSize < (LITTLE_MEMORY_SIZE * MULTIPLE_SIZE * MULTIPLE_SIZE)) {
717                 return true;
718             }
719         }
720     }
721     return false;
722 }
723 
724 // only for domestic beta
IsBeta()725 bool IsBeta()
726 {
727     std::string userTypeRsp = GetUserType();
728     if (userTypeRsp == USER_DOMESTIC_BETA) {
729         return true;
730     }
731     // default release when usertype param is invalid
732     if (userTypeRsp.empty()) {
733         HLOGE("GetUserType is empty [%s]", userTypeRsp.c_str());
734         return true;
735     }
736     return false;
737 }
738 
IsAllowProfilingUid()739 bool IsAllowProfilingUid()
740 {
741 #if (defined(is_linux) && is_linux) || (defined(is_ohos) && is_ohos)
742     static unsigned int curUid = getuid();
743     HLOGD("curUid is %d\n", curUid);
744     if (ALLOW_UIDS.find(curUid) != ALLOW_UIDS.end()) {
745         return true;
746     }
747     return false;
748 #else
749     return false;
750 #endif
751 }
752 
GetProcessName(int pid)753 std::string GetProcessName(int pid)
754 {
755 #if defined(is_ohos) && is_ohos
756     std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
757     std::string bundleName = ReadFileToString(filePath);
758     return bundleName.substr(0, strlen(bundleName.c_str()));
759 #else
760     return "";
761 #endif
762 }
763 
IsDebugableApp(const std::string & bundleName)764 bool IsDebugableApp(const std::string& bundleName)
765 {
766 #if defined(is_ohos) && is_ohos
767     if (bundleName.empty()) {
768         printf("bundleName is empty!\n");
769         return false;
770     }
771     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
772     if (sam == nullptr) {
773         printf("GetSystemAbilityManager failed!\n");
774         return false;
775     }
776     sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
777     if (remoteObject == nullptr) {
778         printf("Get BundleMgr SA failed!\n");
779         return false;
780     }
781     sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
782     if (proxy == nullptr) {
783         printf("iface_cast failed!\n");
784         return false;
785     }
786 
787     int uid = proxy->GetUidByDebugBundleName(bundleName, Constants::ANY_USERID);
788     if (uid < 0) {
789         HLOGE("Get application info failed, bundleName:%s, uid is %d.", bundleName.c_str(), uid);
790         return false;
791     }
792     return true;
793 #else
794     return false;
795 #endif
796 }
797 
AdaptSandboxPath(std::string filePath,int pid)798 std::string AdaptSandboxPath(std::string filePath, int pid)
799 {
800     if (filePath.find("/data/storage") == 0 && access(filePath.c_str(), F_OK) != 0) {
801         filePath = "/proc/" + std::to_string(pid) + "/root" + filePath;
802     }
803     return filePath;
804 }
805 
806 } // namespace HiPerf
807 } // namespace Developtools
808 } // namespace OHOS
809 
810 // this will also used for libunwind head (out of namespace)
811 #if defined(is_mingw) && is_mingw
812 using namespace OHOS::Developtools::HiPerf;
GetLastErrorString()813 std::string GetLastErrorString()
814 {
815     LPVOID lpMsgBuf;
816     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
817                       FORMAT_MESSAGE_IGNORE_INSERTS,
818                   NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL);
819     std::string error((LPTSTR)lpMsgBuf);
820     LocalFree(lpMsgBuf);
821     return error;
822 }
823 
mmap(void * addr,size_t length,int prot,int flags,int fd,size_t offset)824 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset)
825 {
826     HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
827     if (FileHandle == INVALID_HANDLE_VALUE) {
828         return MMAP_FAILED;
829     }
830 
831     HLOGV("fd is %d", fd);
832 
833     HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
834     if (FileMappingHandle == nullptr) {
835         HLOGE("CreateFileMappingW %zu Failed with %ld:%s", length, GetLastError(),
836               GetLastErrorString().c_str());
837         return MMAP_FAILED;
838     }
839 
840     void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
841     if (mapAddr == nullptr) {
842         HLOGE("MapViewOfFile %zu Failed with %ld:%s", length, GetLastError(),
843               GetLastErrorString().c_str());
844         return MMAP_FAILED;
845     }
846 
847     // Close all the handles except for the view. It will keep the other handles
848     // alive.
849     ::CloseHandle(FileMappingHandle);
850     return mapAddr;
851 }
852 
munmap(void * addr,size_t)853 int munmap(void *addr, size_t)
854 {
855     /*
856         On success, munmap() returns 0.  On failure, it returns -1, and
857         errno is set to indicate the error (probably to EINVAL).
858 
859         UnmapViewOfFile function (memoryapi.h)
860 
861         If the function succeeds, the return value is nonzero.
862         If the function fails, the return value is zero. To get extended error information, call
863     GetLastError.
864     */
865     return !UnmapViewOfFile(addr);
866 }
867 #endif
868