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