• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 
16 #include "dfx_util.h"
17 
18 #if defined(is_mingw) && is_mingw
19 #include <memoryapi.h>
20 #include <windows.h>
21 #endif
22 #ifndef is_host
23 #include <cctype>
24 #include <climits>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 #include <ctime>
29 #include <securec.h>
30 #include <sys/types.h>
31 #include <sys/time.h>
32 #include <fcntl.h>
33 #include <pthread.h>
34 #include <unistd.h>
35 #include <dirent.h>
36 #endif
37 #include <sys/stat.h>
38 
39 #include "dfx_log.h"
40 #if !defined(is_ohos_lite) && !defined(DFX_UTIL_STATIC)
41 #include "parameters.h"
42 #endif // !is_ohos_lite
43 
44 #ifdef LOG_DOMAIN
45 #undef LOG_DOMAIN
46 #define LOG_DOMAIN 0xD002D11
47 #endif
48 
49 #ifdef LOG_TAG
50 #undef LOG_TAG
51 #define LOG_TAG "DfxUtil"
52 #endif
53 
54 namespace OHOS {
55 namespace HiviewDFX {
56 #ifndef is_host
TrimAndDupStr(const std::string & source,std::string & str)57 bool TrimAndDupStr(const std::string &source, std::string &str)
58 {
59     if (source.empty()) {
60         return false;
61     }
62 
63     const char *begin = source.data();
64     const char *end = begin + source.size();
65     if (begin == end) {
66         DFXLOGE("Source is empty");
67         return false;
68     }
69 
70     while ((begin < end) && isspace(*begin)) {
71         begin++;
72     }
73 
74     while ((begin < end) && isspace(*(end - 1))) {
75         end--;
76     }
77 
78     if (begin == end) {
79         return false;
80     }
81 
82     uint32_t maxStrLen = NAME_BUF_LEN;
83     uint32_t offset = static_cast<uint32_t>(end - begin);
84     if (maxStrLen > offset) {
85         maxStrLen = offset;
86     }
87 
88     str.assign(begin, maxStrLen);
89     return true;
90 }
91 
GetTimeMilliSeconds(void)92 uint64_t GetTimeMilliSeconds(void)
93 {
94     struct timespec ts;
95     (void)clock_gettime(CLOCK_REALTIME, &ts);
96     return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
97         (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
98 }
99 
GetAbsTimeMilliSeconds(void)100 uint64_t GetAbsTimeMilliSeconds(void)
101 {
102     struct timespec ts;
103     (void)clock_gettime(CLOCK_MONOTONIC, &ts);
104     return (static_cast<uint64_t>(ts.tv_sec) * NUMBER_ONE_THOUSAND) +
105         (static_cast<uint64_t>(ts.tv_nsec) / NUMBER_ONE_MILLION);
106 }
107 
GetCurrentTimeStr(uint64_t current)108 std::string GetCurrentTimeStr(uint64_t current)
109 {
110     time_t now = time(nullptr);
111     uint64_t millsecond = 0;
112     const uint64_t ratio = NUMBER_ONE_THOUSAND;
113     if (current > static_cast<uint64_t>(now)) {
114         millsecond = current % ratio;
115         now = static_cast<time_t>(current / ratio);
116     }
117 
118     auto tm = std::localtime(&now);
119     char seconds[128] = {0}; // 128 : time buffer size
120     if (tm == nullptr || strftime(seconds, sizeof(seconds) - 1, "%Y-%m-%d %H:%M:%S", tm) == 0) {
121         return "invalid timestamp\n";
122     }
123 
124     char millBuf[256] = {0}; // 256 : milliseconds buffer size
125     int ret = snprintf_s(millBuf, sizeof(millBuf), sizeof(millBuf) - 1,
126         "%s.%03u\n", seconds, millsecond);
127     if (ret <= 0) {
128         return "invalid timestamp\n";
129     }
130     return std::string(millBuf, strlen(millBuf));
131 }
132 
ReadDirFiles(const std::string & path,std::vector<std::string> & files)133 bool ReadDirFiles(const std::string& path, std::vector<std::string>& files)
134 {
135     DIR *dir = opendir(path.c_str());
136     if (dir == nullptr) {
137         return false;
138     }
139 
140     struct dirent *ent;
141     while ((ent = readdir(dir)) != nullptr) {
142         // current dir OR parent dir
143         if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) {
144             continue;
145         }
146         files.emplace_back(std::string(ent->d_name));
147     }
148     (void)closedir(dir);
149     return (files.size() > 0);
150 }
151 
VerifyFilePath(const std::string & filePath,const std::vector<const std::string> & validPaths)152 bool VerifyFilePath(const std::string& filePath, const std::vector<const std::string>& validPaths)
153 {
154     if (validPaths.size() == 0) {
155         return true;
156     }
157 
158     for (auto validPath : validPaths) {
159         if (filePath.find(validPath) == 0) {
160             return true;
161         }
162     }
163     return false;
164 }
165 
ParseSiValue(siginfo_t & si,uint64_t & endTime,int & tid)166 void ParseSiValue(siginfo_t& si, uint64_t& endTime, int& tid)
167 {
168     const int flagOffset = 63;
169     if ((reinterpret_cast<uint64_t>(si.si_value.sival_ptr) & (1ULL << flagOffset)) != 0) {
170         endTime = reinterpret_cast<uint64_t>(si.si_value.sival_ptr) & (~(1ULL << flagOffset));
171         tid = 0;
172     } else {
173         endTime = 0;
174         tid = si.si_value.sival_int;
175     }
176 }
177 #endif
178 
GetFileSize(const int & fd)179 off_t GetFileSize(const int& fd)
180 {
181     off_t fileSize = 0;
182     if (fd >= 0) {
183         struct stat fileStat;
184         if (fstat(fd, &fileStat) == 0) {
185             fileSize = fileStat.st_size;
186         }
187     }
188     return fileSize;
189 }
190 
ReadFdToString(int fd,std::string & content)191 bool ReadFdToString(int fd, std::string& content)
192 {
193     content.clear();
194     struct stat sb;
195     if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
196         content.reserve(sb.st_size);
197     }
198 
199     char buf[BUFSIZ] __attribute__((__uninitialized__));
200     ssize_t n;
201     while ((n = OHOS_TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
202         content.append(buf, n);
203     }
204     return (n == 0);
205 }
206 
CloseFd(int & fd)207 void CloseFd(int &fd)
208 {
209     if (fd > 0) {
210         close(fd);
211         fd = -1;
212     }
213 }
214 
StripPac(uintptr_t inAddr,uintptr_t pacMask)215 uintptr_t StripPac(uintptr_t inAddr, uintptr_t pacMask)
216 {
217     uintptr_t outAddr = inAddr;
218 #if defined(__aarch64__)
219     if (outAddr != 0) {
220         if (pacMask != 0) {
221             outAddr &= ~pacMask;
222         } else {
223             register uint64_t x30 __asm("x30") = inAddr;
224             asm("hint 0x7" : "+r"(x30));
225             outAddr = x30;
226         }
227     }
228 #endif
229     return outAddr;
230 }
231 
IsBetaVersion()232 bool IsBetaVersion()
233 {
234 #if !defined(is_ohos_lite) && !defined(DFX_UTIL_STATIC)
235     const char *const logsystemVersionType = "const.logsystem.versiontype";
236     static bool isBetaVersion = OHOS::system::GetParameter(logsystemVersionType, "") == "beta";
237     return isBetaVersion;
238 #else
239     return false;
240 #endif
241 }
242 
IsDeveloperMode()243 bool IsDeveloperMode()
244 {
245 #if !defined(is_ohos_lite) && !defined(DFX_UTIL_STATIC)
246     const char *const developerMode = "const.security.developermode.state";
247     static bool isDeveloperMode = OHOS::system::GetParameter(developerMode, "") == "true";
248     return isDeveloperMode;
249 #else
250     return false;
251 #endif
252 }
253 }   // namespace HiviewDFX
254 }   // namespace OHOS
255 
256 // this will also used for libunwinder head (out of namespace)
257 #if defined(is_mingw) && is_mingw
GetLastErrorString()258 std::string GetLastErrorString()
259 {
260     LPVOID lpMsgBuf;
261     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
262                       FORMAT_MESSAGE_IGNORE_INSERTS,
263                   NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL);
264     std::string error((LPTSTR)lpMsgBuf);
265     LocalFree(lpMsgBuf);
266     return error;
267 }
268 
mmap(void * addr,size_t length,int prot,int flags,int fd,size_t offset)269 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset)
270 {
271     HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
272     if (FileHandle == INVALID_HANDLE_VALUE) {
273         return MMAP_FAILED;
274     }
275 
276     DFXLOGD("fd is %{public}d", fd);
277 
278     HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
279     if (FileMappingHandle == nullptr) {
280         DFXLOGE("CreateFileMappingW %{public}zu Failed with %{public}ld:%{public}s",
281             length, GetLastError(), GetLastErrorString().c_str());
282         return MMAP_FAILED;
283     }
284 
285     void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
286     if (mapAddr == nullptr) {
287         DFXLOGE("MapViewOfFile %{public}zu Failed with %{public}ld:%{public}s",
288             length, GetLastError(), GetLastErrorString().c_str());
289         return MMAP_FAILED;
290     }
291 
292     // Close all the handles except for the view. It will keep the other handles
293     // alive.
294     ::CloseHandle(FileMappingHandle);
295     return mapAddr;
296 }
297 
munmap(void * addr,size_t)298 int munmap(void *addr, size_t)
299 {
300     /*
301         On success, munmap() returns 0.  On failure, it returns -1, and
302         errno is set to indicate the error (probably to EINVAL).
303 
304         UnmapViewOfFile function (memoryapi.h)
305 
306         If the function succeeds, the return value is nonzero.
307         If the function fails, the return value is zero. To get extended error information, call
308     GetLastError.
309     */
310     return !UnmapViewOfFile(addr);
311 }
312 #endif
313