1 /*
2 * Copyright (c) 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 #ifdef _WIN32
17 #include <io.h>
18 #else
19 #include <unistd.h>
20 #endif
21 #include <sys/stat.h>
22 #include <ctime>
23 #include <sstream>
24 #include "ecmascript/dfx/hprof/rawheap_translate/utils.h"
25
26 namespace rawheap_translate {
CheckVersion(const std::string & version)27 bool CheckVersion(const std::string &version)
28 {
29 std::vector<int> result {};
30 std::stringstream ss(version);
31 std::string token;
32 while (getline(ss, token, '.')) {
33 int number;
34 std::istringstream(token) >> number;
35 result.push_back(number);
36 }
37
38 // 3: means the version format is x.x.x
39 if (result.size() != 3) {
40 LOG_ERROR("current version " + version + " is illegal!");
41 return false;
42 }
43
44 bool majorVersionCheckFalse = result[MAJOR_VERSION_INDEX] > VERSION[MAJOR_VERSION_INDEX];
45 bool minorVersionCheckFalse = result[MAJOR_VERSION_INDEX] == VERSION[MAJOR_VERSION_INDEX] &&
46 result[MINOR_VERSION_INDEX] > VERSION[MINOR_VERSION_INDEX];
47 bool buildVersionCheckFalse = result[MAJOR_VERSION_INDEX] == VERSION[MAJOR_VERSION_INDEX] &&
48 result[MINOR_VERSION_INDEX] == VERSION[MINOR_VERSION_INDEX] &&
49 result[BUILD_VERSION_INDEX] > VERSION[BUILD_VERSION_INDEX];
50 if (majorVersionCheckFalse || minorVersionCheckFalse || buildVersionCheckFalse) {
51 std::ostringstream oss;
52 oss << "The rawheap file's version " << version;
53 oss << " is not matched the current rawheap translator, please use the newest version of the translator!";
54 LOG_ERROR(oss.str());
55 return false;
56 };
57 return true;
58 }
59
RealPath(const std::string & filename,std::string & realpath)60 bool RealPath(const std::string &filename, std::string &realpath)
61 {
62 if (filename.empty() || filename.size() > PATH_MAX) {
63 LOG_ERROR("filename is illegal!");
64 return false;
65 }
66
67 #ifdef _WIN32
68 if (_access(filename.c_str(), 0) < 0) {
69 #else
70 if (access(filename.c_str(), 0) < 0) {
71 #endif
72 LOG_ERROR("file can not access! filePath=" + filename);
73 return false;
74 }
75
76 char resolvedPath[PATH_MAX];
77 if (strcpy_s(resolvedPath, PATH_MAX, filename.c_str()) != 0) {
78 return false;
79 }
80
81 realpath = resolvedPath;
82 return true;
83 }
84
85 uint64_t GetFileSize(std::string &inputFilePath)
86 {
87 if (inputFilePath.empty()) {
88 return 0;
89 }
90 struct stat fileInfo;
91 if (stat(inputFilePath.c_str(), &fileInfo) == 0) {
92 return fileInfo.st_size;
93 }
94 return 0;
95 }
96
97 bool FileCheckAndOpenBinary(const std::string &rawheapPath, std::ifstream &file, uint32_t &fileSize)
98 {
99 std::string realpath {};
100 if (!RealPath(rawheapPath, realpath)) {
101 LOG_ERROR("file path is illegal! filePath: " + rawheapPath);
102 return false;
103 }
104
105 uint64_t size = GetFileSize(realpath);
106 if (size == 0 || size >= MAX_FILE_SIZE) {
107 LOG_ERROR("file size >= 4GB or size = 0, unsupported!");
108 return false;
109 }
110
111 fileSize = static_cast<uint32_t>(size);
112 file.open(realpath, std::ios::binary);
113 return true;
114 }
115
116 bool GenerateDumpFileName(std::string &filename)
117 {
118 std::time_t t = std::time(nullptr);
119 struct tm *now = localtime(&t);
120 if (now == nullptr) {
121 LOG_ERROR("Failed to converting time to local time!");
122 return false;
123 }
124
125 filename = "hprof_";
126 const int timeStart = 1900; // 1900: means the start of timestamp
127 filename += std::to_string(now->tm_year + timeStart);
128 filename += '-' + std::to_string(now->tm_mon + 1);
129 filename += '-' + std::to_string(now->tm_mday);
130 filename += '-' + std::to_string(now->tm_hour);
131 filename += '-' + std::to_string(now->tm_min);
132 filename += '-' + std::to_string(now->tm_sec);
133 filename += ".heapsnapshot";
134 return true;
135 }
136
137 bool EndsWith(const std::string &str, const std::string &suffix)
138 {
139 if (str.length() < suffix.length()) {
140 return false;
141 }
142 std::string subStr = str.substr(str.length() - suffix.length(), str.length());
143 return subStr == suffix;
144 }
145
146 bool IsLittleEndian()
147 {
148 int i = 1;
149 return *reinterpret_cast<char *>(&i) == 1;
150 }
151
152 uint32_t ByteToU32(char *data)
153 {
154 uint32_t value = *reinterpret_cast<uint32_t *>(data);
155 if (!IsLittleEndian()) {
156 value = (value & 0x000000FF) << 24 |
157 (value & 0x0000FF00) << 8 |
158 (value & 0x00FF0000) >> 8 |
159 (value & 0xFF000000) >> 24;
160 }
161 return value;
162 }
163
164 uint64_t ByteToU64(char *data)
165 {
166 uint64_t value = *reinterpret_cast<uint64_t *>(data);
167 if (!IsLittleEndian()) {
168 value = (value & 0x00000000000000FF) << 56 |
169 (value & 0x000000000000FF00) << 40 |
170 (value & 0x0000000000FF0000) << 24 |
171 (value & 0x00000000FF000000) << 8 |
172 (value & 0x000000FF00000000) >> 8 |
173 (value & 0x0000FF00000000) >> 24 |
174 (value & 0x00FF0000000000) >> 40 |
175 (value & 0xFF000000000000) >> 56;
176 }
177 return value;
178 }
179
180 void ByteToU32Array(char *data, uint32_t *array, uint32_t size)
181 {
182 char *num = data;
183 for (uint32_t i = 0; i < size; i++) {
184 array[i] = ByteToU32(num);
185 num += sizeof(uint32_t);
186 }
187 }
188
189 void ByteToU64Array(char *data, uint64_t *array, uint32_t size)
190 {
191 char *num = data;
192 for (uint32_t i = 0; i < size; i++) {
193 array[i] = ByteToU64(num);
194 num += sizeof(uint64_t);
195 }
196 }
197 } // namespace rawheap_translate