• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
RealPath(const std::string & filename,std::string & realpath)27 bool RealPath(const std::string &filename, std::string &realpath)
28 {
29     if (filename.empty() || filename.size() > PATH_MAX) {
30         LOG_ERROR_ << "filename is illegal!";
31         return false;
32     }
33 
34 #ifdef _WIN32
35     if (_access(filename.c_str(), 0) < 0) {
36 #else
37     if (access(filename.c_str(), 0) < 0) {
38 #endif
39         LOG_ERROR_ << "file can not access! filePath=" << filename;
40         return false;
41     }
42 
43     char resolvedPath[PATH_MAX];
44     if (strcpy_s(resolvedPath, PATH_MAX, filename.c_str()) != 0) {
45         return false;
46     }
47 
48     realpath = resolvedPath;
49     return true;
50 }
51 
52 bool FileCheckAndOpenBinary(const std::string &rawheapPath, std::ifstream &file, uint32_t &fileSize)
53 {
54     std::string realpath {};
55     if (!RealPath(rawheapPath, realpath)) {
56         LOG_ERROR_ << "file path is illegal! filePath: " << rawheapPath;
57         return false;
58     }
59 
60     uint64_t size = FileReader::GetFileSize(realpath);
61     if (size == 0 || size >= MAX_FILE_SIZE) {
62         LOG_ERROR_ << "file size >= 4GB or size = 0, unsupported!";
63         return false;
64     }
65 
66     fileSize = static_cast<uint32_t>(size);
67     file.open(realpath, std::ios::binary);
68     return true;
69 }
70 
71 bool GenerateDumpFileName(std::string &filename)
72 {
73     std::time_t t = std::time(nullptr);
74     struct tm *now = localtime(&t);
75     if (now == nullptr) {
76         LOG_ERROR_ << "failed to converting time to local time!";
77         return false;
78     }
79 
80     filename = "hprof_";
81     const int timeStart = 1900;  // 1900: means the start of timestamp
82     filename += std::to_string(now->tm_year + timeStart);
83     filename += '-' + std::to_string(now->tm_mon + 1);
84     filename += '-' + std::to_string(now->tm_mday);
85     filename += '-' + std::to_string(now->tm_hour);
86     filename += '-' + std::to_string(now->tm_min);
87     filename += '-' + std::to_string(now->tm_sec);
88     filename += ".heapsnapshot";
89     return true;
90 }
91 
92 bool EndsWith(const std::string &str, const std::string &suffix)
93 {
94     if (str.length() < suffix.length()) {
95         return false;
96     }
97     std::string subStr = str.substr(str.length() - suffix.length(), str.length());
98     return subStr == suffix;
99 }
100 
101 bool IsLittleEndian()
102 {
103     int i = 1;
104     return *reinterpret_cast<char *>(&i) == 1;
105 }
106 
107 uint16_t ByteToU16(char *data)
108 {
109     uint32_t value = *reinterpret_cast<uint16_t *>(data);
110     if (!IsLittleEndian()) {
111         value = (value & 0x00FF) << 8 |
112                 (value & 0xFF00) >> 8;
113     }
114     return value;
115 }
116 
117 uint32_t ByteToU32(char *data)
118 {
119     uint32_t value = *reinterpret_cast<uint32_t *>(data);
120     if (!IsLittleEndian()) {
121         value = (value & 0x000000FF) << 24 |
122                 (value & 0x0000FF00) << 8 |
123                 (value & 0x00FF0000) >> 8 |
124                 (value & 0xFF000000) >> 24;
125     }
126     return value;
127 }
128 
129 uint64_t ByteToU64(char *data)
130 {
131     uint64_t value = *reinterpret_cast<uint64_t *>(data);
132     if (!IsLittleEndian()) {
133         value = (value & 0x00000000000000FF) << 56 |
134                 (value & 0x000000000000FF00) << 40 |
135                 (value & 0x0000000000FF0000) << 24 |
136                 (value & 0x00000000FF000000) << 8 |
137                 (value & 0x000000FF00000000) >> 8 |
138                 (value & 0x0000FF00000000) >> 24 |
139                 (value & 0x00FF0000000000) >> 40 |
140                 (value & 0xFF000000000000) >> 56;
141     }
142     return value;
143 }
144 
145 void ByteToU32Array(char *data, uint32_t *array, uint32_t size)
146 {
147     char *num = data;
148     for (uint32_t i = 0; i < size; i++) {
149         array[i] = ByteToU32(num);
150         num += sizeof(uint32_t);
151     }
152 }
153 
154 void ByteToU64Array(char *data, uint64_t *array, uint32_t size)
155 {
156     char *num = data;
157     for (uint32_t i = 0; i < size; i++) {
158         array[i] = ByteToU64(num);
159         num += sizeof(uint64_t);
160     }
161 }
162 
163 bool FileReader::Initialize(const std::string &path)
164 {
165     std::string realPath;
166     if (!RealPath(path, realPath)) {
167         return false;
168     }
169 
170     file_.open(realPath, std::ios::binary);
171     fileSize_= GetFileSize(realPath);
172     return true;
173 }
174 
175 bool FileReader::Read(char *buf, uint32_t size)
176 {
177     if (buf == nullptr) {
178         LOG_ERROR_ << "file buf is nullptr!";
179         return false;
180     }
181     if (file_.read(buf, size).fail()) {
182         LOG_ERROR_ << "read failed!";
183         return false;
184     }
185     return true;
186 }
187 
188 bool FileReader::Seek(uint32_t offset)
189 {
190     if (!file_.is_open()) {
191         LOG_ERROR_ << "file not open!";
192         return false;
193     }
194     file_.clear();
195     if (!file_.seekg(offset)) {
196         LOG_ERROR_ << "set file offset failed, offset=" << offset;
197         return false;
198     }
199     return true;
200 }
201 
202 bool FileReader::ReadArray(std::vector<uint32_t> &array, uint32_t size)
203 {
204     uint32_t dataSize = size * sizeof(uint32_t);
205     std::vector<char> data(dataSize);
206     if (!Read(data.data(), dataSize)) {
207         return false;
208     }
209     ByteToU32Array(data.data(), array.data(), size);
210     return true;
211 }
212 
213 bool FileReader::ReadArray(std::vector<uint64_t> &array, uint32_t size)
214 {
215     uint32_t dataSize = size * sizeof(uint64_t);
216     std::vector<char> data(dataSize);
217     if (!Read(data.data(), dataSize)) {
218         return false;
219     }
220     ByteToU64Array(data.data(), array.data(), size);
221     return true;
222 }
223 
224 bool FileReader::CheckAndGetHeaderAt(uint32_t offset, uint32_t assertNum)
225 {
226     constexpr int HEADER_SIZE = sizeof(uint64_t) / sizeof(uint32_t);
227     std::vector<uint32_t> header(HEADER_SIZE);
228     if (!Seek(offset) || !ReadArray(header, HEADER_SIZE)) {
229         return false;
230     }
231 
232     uint32_t first = header[0];
233     uint32_t second = header[1];
234     if (assertNum != 0 && second != assertNum) {
235         return false;
236     }
237 
238     left_ = first;
239     right_ = second;
240     return true;
241 }
242 
243 uint32_t FileReader::GetFileSize(const std::string &path)
244 {
245     if (path.empty()) {
246         return 0;
247     }
248     struct stat fileInfo;
249     if (stat(path.c_str(), &fileInfo) == 0) {
250         return static_cast<uint32_t>(fileInfo.st_size);
251     }
252     return 0;
253 }
254 
255 bool Version::Parse(const std::string &version)
256 {
257     std::vector<int> result {};
258     std::stringstream ss(version);
259     std::string token;
260     while (getline(ss, token, '.')) {
261         int number;
262         std::istringstream(token) >> number;
263         result.push_back(number);
264     }
265 
266     if (result.size() != 3) {
267         LOG_ERROR_ << "parse version failed! version=" << version;
268         return false;
269     }
270 
271     major_ = result[0];
272     minor_ = result[1];
273     build_ = result[2];
274     return true;
275 }
276 } // namespace rawheap_translate
277