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 void GenerateDumpFileName(std::string &filename)
117 {
118 filename = "hprof_";
119 std::time_t t = std::time(nullptr);
120 struct tm *now = localtime(&t);
121
122 const int timeStart = 1900; // 1900: means the start of timestamp
123 filename += std::to_string(now->tm_year + timeStart);
124 filename += '-' + std::to_string(now->tm_mon + 1);
125 filename += '-' + std::to_string(now->tm_mday);
126 filename += '-' + std::to_string(now->tm_hour);
127 filename += '-' + std::to_string(now->tm_min);
128 filename += '-' + std::to_string(now->tm_sec);
129 filename += ".heapsnapshot";
130 }
131
132 bool EndsWith(const std::string &str, const std::string &suffix)
133 {
134 if (str.length() < suffix.length()) {
135 return false;
136 }
137 std::string subStr = str.substr(str.length() - suffix.length(), str.length());
138 return subStr == suffix;
139 }
140
141 bool IsLittleEndian()
142 {
143 int i = 1;
144 return *reinterpret_cast<char *>(&i) == 1;
145 }
146
147 uint32_t ByteToU32(char *data)
148 {
149 uint32_t value = *reinterpret_cast<uint32_t *>(data);
150 if (!IsLittleEndian()) {
151 value = (value & 0x000000FF) << 24 |
152 (value & 0x0000FF00) << 8 |
153 (value & 0x00FF0000) >> 8 |
154 (value & 0xFF000000) >> 24;
155 }
156 return value;
157 }
158
159 uint64_t ByteToU64(char *data)
160 {
161 uint64_t value = *reinterpret_cast<uint64_t *>(data);
162 if (!IsLittleEndian()) {
163 value = (value & 0x00000000000000FF) << 56 |
164 (value & 0x000000000000FF00) << 40 |
165 (value & 0x0000000000FF0000) << 24 |
166 (value & 0x00000000FF000000) << 8 |
167 (value & 0x000000FF00000000) >> 8 |
168 (value & 0x0000FF00000000) >> 24 |
169 (value & 0x00FF0000000000) >> 40 |
170 (value & 0xFF000000000000) >> 56;
171 }
172 return value;
173 }
174
175 void ByteToU32Array(char *data, uint32_t *array, uint32_t size)
176 {
177 char *num = data;
178 for (uint32_t i = 0; i < size; i++) {
179 array[i] = ByteToU32(num);
180 num += sizeof(uint32_t);
181 }
182 }
183
184 void ByteToU64Array(char *data, uint64_t *array, uint32_t size)
185 {
186 char *num = data;
187 for (uint32_t i = 0; i < size; i++) {
188 array[i] = ByteToU64(num);
189 num += sizeof(uint64_t);
190 }
191 }
192 } // namespace rawheap_translate