• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 
17 #include <zlib.h>
18 #if is_mingw
19 #include <io.h>
20 #endif
21 #include "logging.h"
22 #include "common.h"
23 
24 namespace OHOS {
25 namespace Developtools {
26 namespace NativeDaemon {
27 constexpr uint32_t INT_MAX_LEN = 10;
28 constexpr uint32_t SC_LG_TINY_MIN = 3;
29 constexpr uint32_t LG_QUANTUM = 4;
30 constexpr uint32_t SC_NTINY = LG_QUANTUM - SC_LG_TINY_MIN;
31 constexpr uint32_t SC_LG_TINY_MAXCLASS = (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1);
32 constexpr uint32_t SC_LG_NGROUP = 2;
33 constexpr uint32_t LG_SIZE_CLASS_GROUP = 2;
34 constexpr uint32_t NTBINS = 1;
35 constexpr uint32_t LG_TINY_MAXCLASS = 3;
36 constexpr uint32_t RIGHT_MOVE_1 = 1;
37 constexpr uint32_t RIGHT_MOVE_2 = 2;
38 constexpr uint32_t RIGHT_MOVE_4 = 4;
39 constexpr uint32_t RIGHT_MOVE_8 = 8;
40 constexpr uint32_t RIGHT_MOVE_16 = 16;
41 
RoundUp(uint32_t x,const int align)42 uint32_t RoundUp(uint32_t x, const int align)
43 {
44     return (((x) + (align) >= 1 ? (x) + (align) - 1 : 0) / (align)) * (align);
45 }
46 
StringReplace(std::string source,const std::string & from,const std::string & to)47 std::string StringReplace(std::string source, const std::string &from, const std::string &to)
48 {
49     size_t pos = 0;
50     while ((pos = source.find(from)) != std::string::npos) {
51         // replace
52         source.replace(pos, from.length(), to);
53     }
54     return source;
55 }
56 
GetValueFromJsonFile(const std::string & filePath,const std::string & key)57 int GetValueFromJsonFile(const std::string& filePath, const std::string& key)
58 {
59     std::ifstream inFile(filePath, std::ios::in);
60     int result = -1; // 默认返回值
61     if (!inFile.is_open()) {
62         HLOGE("parse json file: %s is not existed.", filePath.c_str());
63         return result;
64     }
65     std::string fileContent((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
66     cJSON* jsonNode = cJSON_Parse(fileContent.c_str());
67     inFile.close();
68 
69     if (jsonNode == nullptr) {
70         HLOGE("parse json file: %s failed.", filePath.c_str());
71         return result;
72     }
73     do {
74         cJSON* valueNode = cJSON_GetObjectItem(jsonNode, key.c_str());
75         if (valueNode == nullptr) {
76             HLOGE("ParseJson hiprofiler_hook_process_count json node not found.");
77             break;
78         }
79         if (!cJSON_IsNumber(valueNode)) {
80             HLOGE("ParseJson: hiprofiler_hook_process_count item is illegal.");
81             break;
82         }
83         result = valueNode->valueint; // 获取整数值
84     } while (false);
85 
86     // 释放 cJSON 结构体占用的内存
87     cJSON_Delete(jsonNode);
88     return result;
89 }
90 
SubStringCount(const std::string & source,const std::string & sub)91 size_t SubStringCount(const std::string &source, const std::string &sub)
92 {
93     size_t count(0);
94     size_t pos(0);
95     if (sub.empty()) {
96         return source.size();
97     }
98     while ((pos = source.find(sub, pos)) != std::string::npos) {
99         pos += sub.size();
100         count++;
101     }
102     return count;
103 }
104 
StringSplit(std::string source,std::string split)105 std::vector<std::string> StringSplit(std::string source, std::string split)
106 {
107     size_t pos = 0;
108     std::vector<std::string> result;
109 
110     // find
111     if (!split.empty()) {
112         while ((pos = source.find(split)) != std::string::npos) {
113             // split
114             std::string token = source.substr(0, pos);
115             if (!token.empty()) {
116                 result.push_back(token);
117             }
118             source.erase(0, pos + split.length());
119         }
120     }
121     // add last token
122     if (!source.empty()) {
123         result.push_back(source);
124     }
125     return result;
126 }
127 
AdvancedSplitString(const std::string_view & str,const std::string & delimiters,std::vector<std::string> & elems)128 void AdvancedSplitString(const std::string_view& str, const std::string& delimiters, std::vector<std::string>& elems)
129 {
130     std::string::size_type pos = 0;
131     std::string::size_type prev = 0;
132     while ((pos = str.find_first_of(delimiters, prev)) != std::string::npos) {
133         if (pos > prev) {
134             elems.emplace_back(str, prev, pos - prev);
135         }
136         prev = pos + 1;
137     }
138 
139     if (prev < str.size()) {
140         elems.emplace_back(str, prev, str.size() - prev);
141     }
142 }
143 
StdoutRecord(const std::string & tempFile,const std::string & mode)144 StdoutRecord::StdoutRecord(const std::string &tempFile, const std::string &mode)
145 {
146     if (!tempFile.empty()) {
147         recordFile_ = fopen(tempFile.c_str(), mode.c_str());
148         if (recordFile_ == nullptr) {
149             HLOGE("tmpfile create failed '%s' with mode '%s'", tempFile.c_str(), mode.c_str());
150         } else {
151             // auto start it
152             Start();
153         }
154     }
155 }
Start()156 bool StdoutRecord::Start()
157 {
158     content_ = EMPTY_STRING;
159     fflush(stdout);
160 
161     // we will save output here
162     if (recordFile_ == nullptr) {
163         recordFile_ = std::tmpfile();
164     }
165     if (recordFile_ == nullptr) {
166         // try second way
167         std::string fileName = "/data/local/tmp/temp.stdout";
168         recordFile_ = fopen(fileName.c_str(), "w+");
169         if (recordFile_ == nullptr) {
170             HLOGF("tmpfile create failed '%s'", fileName.c_str());
171             return false;
172         }
173     }
174 
175     // we save the stdout
176     stdoutFile_ = OHOS::UniqueFd(dup(STDOUT_FILENO));
177     if (stdoutFile_ == -1) {
178         HLOGF("std dup failed");
179         return false;
180     }
181 
182     // setup temp file as stdout
183     if (dup2(fileno(recordFile_), STDOUT_FILENO) != -1) {
184         stop_ = false;
185         return true;
186     } else {
187         HLOGF("std dup2 failed");
188         return false;
189     }
190 }
191 
Stop()192 std::string StdoutRecord::Stop()
193 {
194     if (stop_)
195         return content_;
196     fflush(stdout);
197     // restore fd
198     dup2(stdoutFile_, STDOUT_FILENO);
199 
200     // return file content
201     if (recordFile_ != nullptr) {
202         const long fileLength = lseek(fileno(recordFile_), 0, SEEK_END);
203         content_.resize(fileLength);
204         lseek(fileno(recordFile_), 0, SEEK_SET);
205         const long len = read(fileno(recordFile_), content_.data(), fileLength);
206         std::fclose(recordFile_);
207         recordFile_ = nullptr;
208         if (len < 0) {
209             HLOGE("tmp file read failed (try read %ld)", fileLength);
210         } else if (len < fileLength) {
211             HLOGE("not all the data is read, lost %ld/%ld bytes", fileLength - len, fileLength);
212         }
213     } else {
214         HLOGE("recordFile_ is nullptr");
215     }
216     stop_ = true;
217     return content_;
218 }
219 
IsDigits(const std::string & str)220 bool IsDigits(const std::string &str)
221 {
222     if (str.empty() || str.size() >= INT_MAX_LEN) {
223         return false;
224     } else {
225         return std::all_of(str.begin(), str.end(), ::isdigit);
226     }
227 }
228 
IsHexDigits(const std::string & str)229 bool IsHexDigits(const std::string &str)
230 {
231     if (str.empty()) {
232         return false;
233     }
234     const std::string prefix {"0x"};
235     std::string effectStr {str};
236     if (prefix.compare(0, prefix.size(), effectStr.substr(0, prefix.size())) == 0) {
237         effectStr = effectStr.substr(prefix.size(), effectStr.size() - prefix.size());
238     }
239     if (effectStr.empty()) {
240         return false;
241     }
242     std::size_t start {0};
243     for (; start < effectStr.size(); ++start) {
244         if (effectStr[start] == '0') {
245             continue;
246         }
247         break;
248     }
249     if (start == effectStr.size()) {
250         effectStr = "0";
251     }
252     return std::all_of(effectStr.begin(), effectStr.end(), ::isxdigit);
253 }
254 
LgFloor(unsigned long val)255 unsigned LgFloor(unsigned long val)
256 {
257     val |= (val >> RIGHT_MOVE_1);
258     val |= (val >> RIGHT_MOVE_2);
259     val |= (val >> RIGHT_MOVE_4);
260     val |= (val >> RIGHT_MOVE_8);
261     val |= (val >> RIGHT_MOVE_16);
262     if (sizeof(val) > 4) {              // 4: sizeThreshold
263         int constant = sizeof(val) * 4; // 4: sizeThreshold
264         val |= (val >> constant);
265     }
266     val++;
267     if (val == 0) {
268         return 8 * sizeof(val) - 1; // 8: 8byte
269     }
270     return __builtin_ffsl(val) - 2; // 2: adjustment
271 }
272 
PowCeil(uint64_t val)273 uint64_t PowCeil(uint64_t val)
274 {
275     size_t msbIndex = LgFloor(val - 1);
276     return 1ULL << (msbIndex + 1);
277 }
278 
ComputeAlign(size_t size)279 size_t ComputeAlign(size_t size)
280 {
281     if (size == 0) {
282         return 0;
283     }
284     unsigned index = 0;
285     if (size <= (static_cast<size_t>(1) << SC_LG_TINY_MAXCLASS)) {
286         unsigned lgTmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1;
287         unsigned lgCeil = LgFloor(PowCeil(size));
288         index = (lgCeil < lgTmin) ? 0 : lgCeil - lgTmin;
289     } else {
290         unsigned floor = LgFloor((size << 1) - 1);
291         unsigned shift = (floor < SC_LG_NGROUP + LG_QUANTUM) ? 0 : floor - (SC_LG_NGROUP + LG_QUANTUM);
292         unsigned grp = shift << SC_LG_NGROUP;
293         unsigned lgDelta = (floor < SC_LG_NGROUP + LG_QUANTUM + 1) ? LG_QUANTUM : floor - SC_LG_NGROUP - 1;
294         size_t deltaInverseMask = static_cast<size_t>(-1) << lgDelta;
295         unsigned mod = ((((size - 1) & deltaInverseMask) >> lgDelta)) & ((static_cast<size_t>(1) << SC_LG_NGROUP) - 1);
296         index = SC_NTINY + grp + mod;
297     }
298 
299     if (index < NTBINS) {
300         return (static_cast<size_t>(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));
301     }
302     size_t reducedIndex = index - NTBINS;
303     size_t grpVal = reducedIndex >> LG_SIZE_CLASS_GROUP;
304     size_t modVal = reducedIndex & ((static_cast<size_t>(1) << LG_SIZE_CLASS_GROUP) - 1);
305     size_t grpSizeMask = ~((!!grpVal) - 1);
306     size_t grpSize = ((static_cast<size_t>(1) << (LG_QUANTUM + (LG_SIZE_CLASS_GROUP - 1))) << grpVal) & grpSizeMask;
307     size_t shiftVal = (grpVal == 0) ? 1 : grpVal;
308     size_t lgDeltaVal = shiftVal + (LG_QUANTUM - 1);
309     size_t modSize = (modVal + 1) << lgDeltaVal;
310     size_t usize = grpSize + modSize;
311     return usize;
312 }
313 
IsDir(const std::string & path)314 bool IsDir(const std::string &path)
315 {
316     struct stat st;
317     if (stat(path.c_str(), &st) == 0) {
318         return S_ISDIR(st.st_mode);
319     }
320     return false;
321 }
322 
IsPath(const std::string & fileName)323 bool IsPath(const std::string &fileName)
324 {
325     HLOG_ASSERT(!fileName.empty());
326     if (fileName[0] == PATH_SEPARATOR) {
327         return true;
328     }
329     const int prefixPathLen = 2;
330     if (fileName.substr(0, prefixPathLen) == "./") {
331         return true;
332     }
333     return false;
334 }
335 
PlatformPathConvert(const std::string & path)336 std::string PlatformPathConvert(const std::string &path)
337 {
338 #if is_mingw
339     return StringReplace(path, "/", "\\");
340 #else
341     return path;
342 #endif
343 }
344 
ReadFileToString(const std::string & fileName)345 std::string ReadFileToString(const std::string &fileName)
346 {
347     std::ifstream inputString(fileName, std::ios::in);
348     if (!inputString) {
349         return EMPTY_STRING;
350     }
351     std::istreambuf_iterator<char> firstIt = {inputString};
352     std::istreambuf_iterator<char> lastIt = {};
353 
354     std::string content(firstIt, lastIt);
355     return content;
356 }
357 
ReadFileToString(const std::string & fileName,std::string & fileData,size_t fileSize)358 bool ReadFileToString(const std::string &fileName, std::string &fileData, size_t fileSize)
359 {
360     fileData.clear();
361     OHOS::UniqueFd fd(open(fileName.c_str(), O_RDONLY | O_BINARY));
362     if (fileSize == 0) {
363         struct stat fileStat;
364         if (fstat(fd.Get(), &fileStat) != -1 && fileStat.st_size > 0) {
365             fileData.reserve(fileStat.st_size);
366         }
367     } else {
368         fileData.reserve(fileSize);
369     }
370 
371     char buf[BUFSIZ] __attribute__((__uninitialized__));
372     ssize_t readSize;
373     while ((readSize = read(fd.Get(), &buf[0], sizeof(buf))) > 0) {
374         fileData.append(buf, readSize);
375     }
376     return (readSize == 0) ? true : false;
377 }
378 
WriteStringToFile(const std::string & fileName,const std::string & value)379 bool WriteStringToFile(const std::string &fileName, const std::string &value)
380 {
381     std::ofstream output(fileName, std::ios::out);
382     if (!output) {
383         return false;
384     }
385     output << value;
386 
387     return output.good();
388 }
389 
PowerOfTwo(int n)390 bool PowerOfTwo(int n)
391 {
392     return n && (!(n & (n - 1)));
393 }
394 
ReadIntFromProcFile(const std::string & path,int & value)395 bool ReadIntFromProcFile(const std::string &path, int &value)
396 {
397     std::string s = ReadFileToString(path);
398     if (s.empty()) {
399         return false;
400     }
401     value = IsDigits(s) ? std::stoi(s) : 0;
402     return true;
403 }
404 
WriteIntToProcFile(const std::string & path,int value)405 bool WriteIntToProcFile(const std::string &path, int value)
406 {
407     std::string s = std::to_string(value);
408 
409     return WriteStringToFile(path, s);
410 }
411 
412 // compress specified dataFile into gzip file
CompressFile(const std::string & dataFile,const std::string & destFile)413 bool CompressFile(const std::string &dataFile, const std::string &destFile)
414 {
415     FILE *fp = fopen(dataFile.c_str(), "rb");
416     if (fp == nullptr) {
417         HLOGE("Fail to open data file %s", dataFile.c_str());
418         perror("Fail to fopen(rb)");
419         return false;
420     }
421 
422     std::unique_ptr<gzFile_s, decltype(&gzclose)> fgz(gzopen(destFile.c_str(), "wb"), gzclose);
423     if (fgz == nullptr) {
424         HLOGE("Fail to call gzopen(%s)", destFile.c_str());
425         fclose(fp);
426         return false;
427     }
428 
429     std::vector<char> buf(COMPRESS_READ_BUF_SIZE);
430     size_t len = 0;
431     while ((len = fread(buf.data(), sizeof(uint8_t), buf.size(), fp))) {
432         if (gzwrite(fgz.get(), buf.data(), len) == 0) {
433             HLOGE("Fail to call gzwrite for %zu bytes", len);
434             fclose(fp);
435             return false;
436         }
437     }
438     if (!feof(fp)) {
439         if (ferror(fp) != 0) {
440             HLOGE("ferror return err");
441             fclose(fp);
442             return false;
443         }
444     }
445     const int errBufSize = 256;
446     char errBuf[errBufSize] = { 0 };
447     strerror_r(errno, errBuf, errBufSize);
448     UNWIND_CHECK_TRUE(fclose(fp) == 0, false, "fclose failed! errno(%d:%s)", errno, errBuf);
449     return true;
450 }
451 
452 // uncompress specified gzip file into dataFile
UncompressFile(const std::string & gzipFile,const std::string & dataFile)453 bool UncompressFile(const std::string &gzipFile, const std::string &dataFile)
454 {
455     FILE *fp = fopen(dataFile.c_str(), "wb");
456     if (fp == nullptr) {
457         HLOGE("Fail to open data file %s", dataFile.c_str());
458         perror("Fail to fopen(rb)");
459         return false;
460     }
461     std::unique_ptr<gzFile_s, decltype(&gzclose)> fgz(gzopen(gzipFile.c_str(), "rb"), gzclose);
462     if (fgz == nullptr) {
463         HLOGE("Fail to call gzopen(%s)", gzipFile.c_str());
464         fclose(fp);
465         return false;
466     }
467 
468     std::vector<char> buf(COMPRESS_READ_BUF_SIZE);
469     z_size_t len = 0;
470     while ((len = gzfread(buf.data(), sizeof(uint8_t), buf.size(), fgz.get()))) {
471         if (len != fwrite(buf.data(), sizeof(uint8_t), len, fp)) {
472             HLOGE("Fail to call fwrite for %zu bytes", len);
473             fclose(fp);
474             return false;
475         }
476     }
477     if (!gzeof(fgz.get())) {
478         int rc = 0;
479         const char *err = gzerror(fgz.get(), &rc);
480         if (rc != Z_OK) {
481             HLOGE("gzfread return %d:%s", rc, err);
482             fclose(fp);
483             return false;
484         }
485     }
486     const int size = 256;
487     char errBuf[size] = { 0 };
488     strerror_r(errno, errBuf, size);
489     UNWIND_CHECK_TRUE(fclose(fp) == 0, false, "fclose failed! errno(%d:%s)", errno, errBuf);
490     return true;
491 }
492 
StringTrim(std::string & string)493 std::string &StringTrim(std::string &string)
494 {
495     if (!string.empty()) {
496         string.erase(0, string.find_first_not_of(" "));
497         string.erase(string.find_last_not_of(" ") + 1);
498     }
499     return string;
500 }
501 
GetEntriesInDir(const std::string & basePath)502 std::vector<std::string> GetEntriesInDir(const std::string &basePath)
503 {
504     std::vector<std::string> result;
505     DIR *dir = opendir(basePath.c_str());
506     if (dir == nullptr) {
507         return result;
508     }
509     dirent *entry;
510     while ((entry = readdir(dir)) != nullptr) {
511         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
512             continue;
513         }
514         result.push_back(entry->d_name);
515     }
516     closedir(dir);
517     return result;
518 }
519 
GetSubDirs(const std::string & basePath)520 std::vector<std::string> GetSubDirs(const std::string &basePath)
521 {
522     std::vector<std::string> entries = GetEntriesInDir(basePath);
523     std::vector<std::string> result = {};
524     for (std::size_t index = 0; index < entries.size(); ++index) {
525         if (IsDir(basePath + "/" + entries[index])) {
526             result.push_back(std::move(entries[index]));
527         }
528     }
529     return result;
530 }
531 
IsSameCommand(std::string cmdLine,std::string cmdName)532 bool IsSameCommand(std::string cmdLine, std::string cmdName)
533 {
534     std::vector<std::string> cmdpaths = StringSplit(cmdLine, "/");
535     if (!cmdpaths.empty()) {
536         if (strcmp(cmdpaths.back().c_str(), cmdName.c_str()) == 0) {
537             return true;
538         }
539     }
540     return false;
541 }
542 
GetSubthreadIDs(const pid_t pid)543 std::vector<pid_t> GetSubthreadIDs(const pid_t pid)
544 {
545     std::string path {"/proc/"};
546     path += std::to_string(pid);
547     path += "/task/";
548     auto tids = GetSubDirs(path);
549     std::vector<pid_t> res {};
550     for (auto tidStr : tids) {
551         pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr));
552         if (tid == pid) {
553             continue;
554         }
555         res.push_back(tid);
556     }
557     return res;
558 }
559 
StringStartsWith(const std::string & string,const std::string & with)560 bool StringStartsWith(const std::string &string, const std::string &with)
561 {
562     return string.find(with) == 0;
563 }
564 
StringEndsWith(const std::string & string,const std::string & with)565 bool StringEndsWith(const std::string &string, const std::string &with)
566 {
567     if (string.empty()) {
568         // empty string only end with empty string
569         if (with.empty()) {
570             return true;
571         } else {
572             return false;
573         }
574     }
575     return string.rfind(with) == (string.length() - with.length());
576 }
577 
HexDump(const uint8_t * buf,size_t size,size_t maxSize)578 void HexDump(const uint8_t *buf, size_t size, size_t maxSize)
579 {
580     const unsigned char *byteBuf = static_cast<const unsigned char *>(buf);
581     const size_t dumpByteEachLine = 8;
582     size_t outputBytes = 0;
583     if (!maxSize) {
584         outputBytes = size;
585     } else {
586         outputBytes = std::min(size, maxSize);
587     }
588 
589     for (size_t i = 0; i <= outputBytes; i += dumpByteEachLine) {
590         HLOGM(" %02zu: %s ", i, BufferToHexString(byteBuf, dumpByteEachLine).c_str());
591         byteBuf += dumpByteEachLine;
592     }
593 }
594 
BufferToHexString(const std::vector<unsigned char> & vec)595 std::string BufferToHexString(const std::vector<unsigned char> &vec)
596 {
597     return BufferToHexString(vec.data(), vec.size());
598 }
599 
BufferToHexString(const unsigned char buf[],size_t size)600 std::string BufferToHexString(const unsigned char buf[], size_t size)
601 {
602     std::stringstream ss;
603     ss << size << ":";
604     for (size_t i = 0; i < size; i++) {
605         ss << " 0x" << std::setfill('0') << std::setw(BYTE_PRINT_WIDTH) << std::hex
606            << (unsigned short)buf[i];
607     }
608     return ss.str();
609 }
610 
GetProcessPid(const std::string & processName)611 int32_t GetProcessPid(const std::string& processName)
612 {
613     int32_t pidValue = -1;
614     COMMON::IsProcessExist(processName, pidValue);
615     return pidValue;
616 }
IsArkJsFile(const std::string & filepath)617 bool IsArkJsFile(const std::string& filepath)
618 {
619     return (StringEndsWith(filepath, ".hap") || StringEndsWith(filepath, ".hsp") ||
620             StringStartsWith(filepath, "[anon:ArkTS Code") || StringEndsWith(filepath, ".abc")
621             || StringEndsWith(filepath, ".hqf"));
622 }
623 
StripPac(uintptr_t inAddr,uintptr_t pacMask)624 uintptr_t StripPac(uintptr_t inAddr, uintptr_t pacMask)
625 {
626     uintptr_t outAddr = inAddr;
627 #if defined(__aarch64__)
628     if (outAddr != 0) {
629         if (pacMask != 0) {
630             outAddr &= ~pacMask;
631         } else {
632             register uint64_t x30 __asm("x30") = inAddr;
633             asm("hint 0x7" : "+r"(x30));
634             outAddr = x30;
635         }
636     }
637 #endif
638     return outAddr;
639 }
640 } // namespace NativeDaemon
641 } // namespace Developtools
642 } // namespace OHOS
643 
644 // this will also used for libunwind head (out of namespace)
645 #if is_mingw
646 using namespace OHOS::Developtools::NativeDaemon;
GetLastErrorString()647 std::string GetLastErrorString()
648 {
649     LPVOID lpMsgBuf;
650     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
651                   FORMAT_MESSAGE_IGNORE_INSERTS,
652                   nullptr, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, nullptr);
653     std::string error((LPTSTR)lpMsgBuf);
654     LocalFree(lpMsgBuf);
655     return error;
656 }
657 
mmap(void * addr,size_t length,int prot,int flags,int fd,size_t offset)658 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset)
659 {
660     HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
661     if (FileHandle == INVALID_HANDLE_VALUE) {
662         return MMAP_FAILED;
663     }
664 
665     HLOGV("fd is %d", fd);
666 
667     HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
668     UNWIND_CHECK_NOTNULL(FileMappingHandle, MMAP_FAILED, "CreateFileMappingW %zu Failed with %ld:%s",
669                          length, GetLastError(), GetLastErrorString().c_str());
670 
671     void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
672     UNWIND_CHECK_NOTNULL(mapAddr, MMAP_FAILED, "MapViewOfFile %zu Failed with %ld:%s",
673                          length, GetLastError(), GetLastErrorString().c_str());
674 
675     // Close all the handles except for the view. It will keep the other handles
676     // alive.
677     ::CloseHandle(FileMappingHandle);
678     return mapAddr;
679 }
680 
munmap(void * addr,size_t)681 int munmap(void *addr, size_t)
682 {
683     /*
684         On success, munmap() returns 0.  On failure, it returns -1, and
685         errno is set to indicate the error (probably to EINVAL).
686 
687         UnmapViewOfFile function (memoryapi.h)
688 
689         If the function succeeds, the return value is nonzero.
690         If the function fails, the return value is zero. To get extended error information, call
691     GetLastError.
692     */
693     return !UnmapViewOfFile(addr);
694 }
695 #endif