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