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 #include "ecmascript/compiler/aot_file/elf_checker.h"
16 #include <fstream>
17 #include <type_traits>
18
19 namespace panda::ecmascript {
20 /* Check Aligned */
CheckAlign(void* alignPtr, size_t offset = 0)21 template <typename AlignType> static bool CheckAlign(void* alignPtr, size_t offset = 0)
22 {
23 if (ALLOW_UNALIGNED != 0) {
24 return true;
25 }
26 size_t ptrPos = reinterpret_cast<size_t>(alignPtr) + offset;
27 if ((ptrPos & (alignof(AlignType) - 1)) == 0) {
28 return true;
29 } else {
30 return false;
31 }
32 }
33
34 /* Swap LSB and MSB */
ByteSwap(IntType& x)35 template <typename IntType> static void ByteSwap(IntType& x)
36 {
37 static constexpr unsigned int iByteMuskOff0 = 0xffu;
38 static constexpr unsigned int iByteMuskOff1 = iByteMuskOff0 << 8;
39 static constexpr unsigned int iByteMuskOff2 = iByteMuskOff1 << 8;
40 static constexpr unsigned int iByteMuskOff3 = iByteMuskOff2 << 8;
41 static constexpr unsigned long long llByteMuskOff0 = 0xffuLL;
42 static constexpr unsigned long long llByteMuskOff1 = llByteMuskOff0 << 8;
43 static constexpr unsigned long long llByteMuskOff2 = llByteMuskOff1 << 8;
44 static constexpr unsigned long long llByteMuskOff3 = llByteMuskOff2 << 8;
45 static constexpr unsigned long long llByteMuskOff4 = llByteMuskOff3 << 8;
46 static constexpr unsigned long long llByteMuskOff5 = llByteMuskOff4 << 8;
47 static constexpr unsigned long long llByteMuskOff6 = llByteMuskOff5 << 8;
48 static constexpr unsigned long long llByteMuskOff7 = llByteMuskOff6 << 8;
49 static constexpr unsigned int move1 = 8; // 8: move 8 bits
50 static constexpr unsigned int move2 = move1 + 8 * 2; // 8: skip one pair
51 static constexpr unsigned int move3 = move2 + 8 * 2; // 8: skip another pair
52 static constexpr unsigned int move4 = move3 + 8 * 2; // 8: skip another pair
53 switch (sizeof(IntType)) {
54 case sizeof(int8_t):
55 return;
56 case sizeof(int16_t):
57 x = IntType((((x) >> move1) & iByteMuskOff0) |
58 (((x) & iByteMuskOff0) << move1)); // 8: position to change between LSB and MSB
59 return;
60 case sizeof(int32_t):
61 x = ((((x) & iByteMuskOff3) >> move2) | (((x) & iByteMuskOff2) >> move1) |
62 (((x) & iByteMuskOff1) << move1) | (((x) & iByteMuskOff0) << move2));
63 return;
64 case sizeof(int64_t):
65 x = ((((x) & llByteMuskOff7) >> move4) | (((x) & llByteMuskOff6) >> move3) |
66 (((x) & llByteMuskOff5) >> move2) | (((x) & llByteMuskOff4) >> move1) |
67 (((x) & llByteMuskOff3) << move1) | (((x) & llByteMuskOff2) << move2) |
68 (((x) & llByteMuskOff1) << move3) | (((x) & llByteMuskOff0) << move4));
69 return;
70 default:
71 return;
72 }
73 }
74
75 /* This function requires copying memory. Avoid using it if MemMap is avalible. */
ElfChecker(const void* data, int len)76 ElfChecker::ElfChecker(const void* data, int len) : elfLen_(len), elfErrorCode_(0), fromMmap_(false)
77 {
78 if (len <= 0 || data == nullptr) {
79 elfData_ = nullptr;
80 return;
81 }
82 elfData_ = new char[len];
83 if (memcpy_s(elfData_, len, data, len) != 0) {
84 delete[] elfData_;
85 elfData_ = nullptr;
86 return;
87 }
88 }
89
ElfChecker(const std::string& path)90 ElfChecker::ElfChecker(const std::string& path) : elfErrorCode_(0), fromMmap_(false)
91 {
92 if (!panda::ecmascript::FileExist(path.c_str())) {
93 elfData_ = nullptr;
94 elfLen_ = 0;
95 return;
96 }
97 std::ifstream file(path, std::ios::binary | std::ios::ate);
98 if (file.is_open() == false) {
99 elfData_ = nullptr;
100 elfLen_ = 0;
101 return;
102 }
103 elfLen_ = static_cast<size_t>(file.tellg());
104 file.seekg(0, std::ios::beg);
105 if (elfLen_ <= 0) {
106 elfData_ = nullptr;
107 return;
108 }
109 elfData_ = new char[elfLen_];
110 file.read(elfData_, elfLen_);
111 return;
112 }
113
ElfChecker(const MemMap& mem)114 ElfChecker::ElfChecker(const MemMap& mem) : elfErrorCode_(0), fromMmap_(true)
115 {
116 elfData_ = reinterpret_cast<char*>(mem.GetMem());
117 elfLen_ = mem.GetSize();
118 if (elfLen_ == 0) {
119 elfData_ = nullptr;
120 }
121 }
122
CheckValidElf()123 bool ElfChecker::CheckValidElf()
124 {
125 if (elfData_ == nullptr || elfLen_ <= 0) {
126 return false;
127 }
128 Elf* elf = ElfMemory(elfData_, elfLen_);
129 if (elf == nullptr || elf->kind == ELF_KIND_NONE || CheckIfError() == false) {
130 ElfRelease(elf);
131 return false;
132 }
133 int release_num = ElfRelease(elf);
134 if (release_num != 0 || CheckIfError() == false) {
135 return false;
136 }
137 return true;
138 }
139
CheckIfError() const140 int ElfChecker::CheckIfError() const
141 {
142 if (elfErrorCode_ != ELF_ERR_NOERROR) {
143 return false;
144 }
145 return true;
146 }
147
SetErrorCode(int value)148 void ElfChecker::SetErrorCode(int value)
149 {
150 if (value >= 0 && value < ELF_ERR_NUM) {
151 elfErrorCode_ = value;
152 } else {
153 elfErrorCode_ = ELF_ERR_UNKNOWN_ERROR;
154 }
155 }
156
ElfAllocate( void* mapAddress, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent, ElfKind kind, size_t extra)157 ElfChecker::Elf* ElfChecker::ElfAllocate(
158 void* mapAddress, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent, ElfKind kind, size_t extra)
159 {
160 size_t alloc_size = sizeof(Elf) + extra;
161 Elf* result = reinterpret_cast<Elf*>(new char[alloc_size]());
162 if (result == nullptr) {
163 SetErrorCode(ELF_ERR_NOMEM);
164 } else {
165 result->kind = kind;
166 result->refCount = 1;
167 result->cmd = cmd;
168 result->startOffset = offset;
169 result->maxSize = maxsize;
170 result->mapAddress = mapAddress;
171 result->parent = parent;
172 }
173
174 return result;
175 }
176
GetElfKind(void* buf) const177 ElfChecker::ElfKind ElfChecker::GetElfKind(void* buf) const
178 {
179 /* Could be an ELF file. */
180 int eclass = (int)(reinterpret_cast<unsigned char*>(buf))[llvm::ELF::EI_CLASS];
181 int data = (int)(reinterpret_cast<unsigned char*>(buf))[llvm::ELF::EI_DATA];
182 int version = (int)(reinterpret_cast<unsigned char*>(buf))[llvm::ELF::EI_VERSION];
183
184 if (eclass > llvm::ELF::ELFCLASSNONE && eclass <= llvm::ELF::ELFCLASS64 && data > llvm::ELF::ELFDATANONE &&
185 data <= llvm::ELF::ELFDATA2MSB && version == llvm::ELF::EV_CURRENT) {
186 return ELF_KIND_ELF;
187 }
188
189 /* We do not know this file type. */
190 return ELF_KIND_NONE;
191 }
192
193 /* Get the number of sections from the ELF header. */
194 template <typename FromElfHeader, typename FromElfSectionHeader, typename SizeType>
GetSectionHeaderNum( FromElfHeader* ehdr, size_t maxsize, unsigned char* eIdent, void* mapAddress, int64_t offset)195 size_t ElfChecker::GetSectionHeaderNum(
196 FromElfHeader* ehdr, size_t maxsize, unsigned char* eIdent, void* mapAddress, int64_t offset)
197 {
198 size_t result = ehdr->e_shnum;
199 if (SECUREC_UNLIKELY(result == 0) && ehdr->e_shoff != 0) {
200 if (SECUREC_UNLIKELY(ehdr->e_shoff >= maxsize) ||
201 SECUREC_UNLIKELY(maxsize - ehdr->e_shoff < sizeof(FromElfSectionHeader))) {
202 return 0;
203 }
204 SizeType size;
205 FromElfSectionHeader* dest =
206 reinterpret_cast<FromElfSectionHeader*>(reinterpret_cast<char*>(mapAddress) + ehdr->e_shoff + offset);
207 if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && CheckAlign<FromElfSectionHeader>(dest) == true) {
208 /* We can directly access the memory. */
209 size = dest->sh_size;
210 } else {
211 char* memSrc =
212 reinterpret_cast<char*>(mapAddress) + ehdr->e_shoff + offset + offsetof(FromElfSectionHeader, sh_size);
213 if (memcpy_s(&size, sizeof(size), memSrc, sizeof(SizeType)) != 0) {
214 SetErrorCode(ELF_ERR_NOMEM);
215 return 0;
216 }
217
218 if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) {
219 ByteSwap(size);
220 }
221 if (size > ~((llvm::ELF::Elf64_Word)0)) {
222 /* Invalid value, it is too large. */
223 SetErrorCode(ELF_ERR_INVALID_ELF);
224 return 0;
225 }
226 }
227 result = size;
228 }
229
230 /* If the section headers were truncated, pretend none were there.
231 */
232 if (ehdr->e_shoff > maxsize || maxsize - ehdr->e_shoff < sizeof(FromElfSectionHeader) * result) {
233 result = 0;
234 }
235 return result;
236 }
237
238 /* Get Section Header Number */
GetShnum(void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxsize)239 size_t ElfChecker::GetShnum(void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxsize)
240 {
241 union {
242 llvm::ELF::Elf32_Ehdr* e32;
243 llvm::ELF::Elf64_Ehdr* e64;
244 void* p;
245 } ehdrPtr;
246 union {
247 llvm::ELF::Elf32_Ehdr e32;
248 llvm::ELF::Elf64_Ehdr e64;
249 } ehdrMem;
250 bool is32 = eIdent[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32;
251
252 if ((is32 && maxsize < sizeof(llvm::ELF::Elf32_Ehdr)) || (!is32 && maxsize < sizeof(llvm::ELF::Elf64_Ehdr))) {
253 /* Not long enough */
254 SetErrorCode(ELF_ERR_INVALID_ELF);
255 return 0;
256 }
257 /* Make the ELF header available. */
258 bool isAligned = (is32 ? CheckAlign<llvm::ELF::Elf32_Ehdr>(eIdent) : CheckAlign<llvm::ELF::Elf64_Ehdr>(eIdent));
259 if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && isAligned) {
260 ehdrPtr.p = eIdent;
261 } else {
262 ehdrPtr.p = &ehdrMem;
263 if (is32) {
264 if (ALLOW_UNALIGNED) {
265 ehdrMem.e32.e_shnum = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(eIdent)->e_shnum;
266 ehdrMem.e32.e_shoff = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(eIdent)->e_shoff;
267 } else {
268 if (memcpy_s(&ehdrMem, sizeof(ehdrMem), eIdent, sizeof(llvm::ELF::Elf32_Ehdr)) != 0) {
269 SetErrorCode(ELF_ERR_NOMEM);
270 return 0;
271 };
272 }
273
274 if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) {
275 ByteSwap(ehdrMem.e32.e_shnum);
276 ByteSwap(ehdrMem.e32.e_shoff);
277 }
278 } else {
279 if (ALLOW_UNALIGNED) {
280 ehdrMem.e64.e_shnum = reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(eIdent)->e_shnum;
281 ehdrMem.e64.e_shoff = reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(eIdent)->e_shoff;
282 } else {
283 if (memcpy_s(&ehdrMem, sizeof(ehdrMem), eIdent, sizeof(llvm::ELF::Elf64_Ehdr)) != 0) {
284 SetErrorCode(ELF_ERR_NOMEM);
285 return 0;
286 }
287 };
288
289 if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) {
290 ByteSwap(ehdrMem.e64.e_shnum);
291 ByteSwap(ehdrMem.e64.e_shoff);
292 }
293 }
294 }
295 if (is32) {
296 return GetSectionHeaderNum<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Shdr, llvm::ELF::Elf32_Word>(
297 ehdrPtr.e32, maxsize, eIdent, mapAddress, offset);
298 } else {
299 return GetSectionHeaderNum<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Shdr, llvm::ELF::Elf64_Xword>(
300 ehdrPtr.e64, maxsize, eIdent, mapAddress, offset);
301 }
302 }
303
304 /* Get Details from mapAddress, */
305 template <typename ElfEhdr, typename ElfShdr, typename ElfItemField>
GetElfItem(ElfItemField& elfItemField, void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxSize, ElfCommand cmd, size_t scnCnt, Elf* elf)306 ElfChecker::Elf* ElfChecker::GetElfItem(ElfItemField& elfItemField, void* mapAddress, unsigned char* eIdent,
307 int64_t offset, size_t maxSize, ElfCommand cmd, size_t scnCnt, Elf* elf)
308 {
309 /* This pointer might not be directly usable if the alignment is
310 not sufficient for the architecture. */
311 ElfEhdr* ehdr = reinterpret_cast<ElfEhdr*>(reinterpret_cast<char*>(mapAddress) + offset);
312 if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && CheckAlign<ElfEhdr>(ehdr)) {
313 /* We can use the mmapped memory. */
314 elfItemField.ehdr = ehdr;
315 } else {
316 if (memcpy_s(&elfItemField.elfHeaderMem, sizeof(ElfEhdr), eIdent, sizeof(ElfEhdr)) != 0) {
317 SetErrorCode(ELF_ERR_NOMEM);
318 return nullptr;
319 }
320 elfItemField.ehdr = reinterpret_cast<ElfEhdr*>(&elfItemField.elfHeaderMem);
321 if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) {
322 ByteSwap(elfItemField.elfHeaderMem.e_type);
323 ByteSwap(elfItemField.elfHeaderMem.e_machine);
324 ByteSwap(elfItemField.elfHeaderMem.e_version);
325 ByteSwap(elfItemField.elfHeaderMem.e_entry);
326 ByteSwap(elfItemField.elfHeaderMem.e_phoff);
327 ByteSwap(elfItemField.elfHeaderMem.e_shoff);
328 ByteSwap(elfItemField.elfHeaderMem.e_flags);
329 ByteSwap(elfItemField.elfHeaderMem.e_ehsize);
330 ByteSwap(elfItemField.elfHeaderMem.e_phentsize);
331 ByteSwap(elfItemField.elfHeaderMem.e_phnum);
332 ByteSwap(elfItemField.elfHeaderMem.e_shentsize);
333 ByteSwap(elfItemField.elfHeaderMem.e_shnum);
334 ByteSwap(elfItemField.elfHeaderMem.e_shstrndx);
335 }
336 }
337 auto elfSHOff = elfItemField.ehdr->e_shoff;
338 if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && cmd != ELF_CMD_READ_MMAP &&
339 CheckAlign<ElfShdr>(ehdr, elfSHOff)) {
340 if (SECUREC_UNLIKELY(scnCnt > 0 && elfSHOff >= maxSize) ||
341 SECUREC_UNLIKELY(maxSize - elfSHOff < scnCnt * sizeof(ElfShdr))) {
342 delete[] reinterpret_cast<char*>(elf);
343 elf = nullptr;
344 SetErrorCode(ELF_ERR_INVALID_ELF);
345 return nullptr;
346 }
347 if (scnCnt > 0) {
348 elfItemField.shdr = reinterpret_cast<ElfShdr*>(reinterpret_cast<char*>(ehdr) + elfSHOff);
349 }
350 for (size_t cnt = 0; cnt < scnCnt; ++cnt) {
351 elfItemField.sections.data()[cnt].index = cnt;
352 elfItemField.sections.data()[cnt].elf = elf;
353 if (std::is_same<ElfShdr, llvm::ELF::Elf32_Shdr>::value) {
354 elfItemField.sections.data()[cnt].shdr.e32 =
355 reinterpret_cast<llvm::ELF::Elf32_Shdr*>(&elfItemField.shdr[cnt]);
356 } else {
357 elfItemField.sections.data()[cnt].shdr.e64 =
358 reinterpret_cast<llvm::ELF::Elf64_Shdr*>(&elfItemField.shdr[cnt]);
359 }
360
361 if (SECUREC_LIKELY(elfItemField.shdr[cnt].sh_offset < maxSize) &&
362 SECUREC_LIKELY(elfItemField.shdr[cnt].sh_size <= maxSize - elfItemField.shdr[cnt].sh_offset)) {
363 elfItemField.sections.data()[cnt].rawDataBase = elfItemField.sections.data()[cnt].dataBase =
364 (reinterpret_cast<char*>(mapAddress) + offset + elfItemField.shdr[cnt].sh_offset);
365 }
366 elfItemField.sections.data()[cnt].list = &elfItemField.sections;
367
368 /* If this is a section with an extended index add a
369 reference in the section which uses the extended
370 index. */
371 if (elfItemField.shdr[cnt].sh_type == llvm::ELF::SHT_SYMTAB_SHNDX &&
372 elfItemField.shdr[cnt].sh_link < scnCnt) {
373 elfItemField.sections.data()[elfItemField.shdr[cnt].sh_link]
374 .extendSectionHeaderIndex = static_cast<int>(cnt);
375 }
376 /* Set the own extendSectionHeaderIndex field in case it has not yet
377 been set. */
378 if (elfItemField.sections.data()[cnt].extendSectionHeaderIndex == 0) {
379 elfItemField.sections.data()[cnt].extendSectionHeaderIndex = -1;
380 }
381 }
382 } else {
383 for (size_t cnt = 0; cnt < scnCnt; ++cnt) {
384 elfItemField.sections.data()[cnt].index = cnt;
385 elfItemField.sections.data()[cnt].elf = elf;
386 elfItemField.sections.data()[cnt].list = &elfItemField.sections;
387 }
388 }
389
390 /* So far only one block with sections. */
391 elfItemField.sectionLast = &elfItemField.sections;
392 return elf;
393 }
394
395 /* Create descriptor for ELF file in memory. */
FileReadElf( void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxSize, ElfCommand cmd, Elf* parent)396 ElfChecker::Elf* ElfChecker::FileReadElf(
397 void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxSize, ElfCommand cmd, Elf* parent)
398 {
399 /* Verify the binary is of the class we can handle. */
400 if (SECUREC_UNLIKELY((eIdent[llvm::ELF::EI_CLASS] != llvm::ELF::ELFCLASS32 &&
401 eIdent[llvm::ELF::EI_CLASS] != llvm::ELF::ELFCLASS64) ||
402 (eIdent[llvm::ELF::EI_DATA] != llvm::ELF::ELFDATA2LSB &&
403 eIdent[llvm::ELF::EI_DATA] != llvm::ELF::ELFDATA2MSB))) {
404 /* Cannot handle this. */
405 SetErrorCode(ELF_ERR_INVALID_ELF);
406 return nullptr;
407 }
408
409 size_t scncnt = GetShnum(mapAddress, eIdent, offset, maxSize);
410 if (CheckIfError() == false) {
411 return nullptr;
412 }
413
414 /* Check for too many sections. */
415 if (eIdent[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) {
416 if (scncnt > SIZE_MAX / (sizeof(ElfSectionBase) + sizeof(llvm::ELF::Elf32_Shdr))) {
417 SetErrorCode(ELF_ERR_INVALID_ELF);
418 return nullptr;
419 }
420 } else if (scncnt > SIZE_MAX / (sizeof(ElfSectionBase) + sizeof(llvm::ELF::Elf64_Shdr))) {
421 SetErrorCode(ELF_ERR_INVALID_ELF);
422 return nullptr;
423 }
424
425 /* We can now allocate the memory. Even if there are no section
426 headers, we allocate space for a zeroth section in case we need it
427 later. */
428 const size_t scnMax = (scncnt ? scncnt : (cmd == ELF_CMD_RDWR || cmd == ELF_CMD_RDWR_MMAP) ? 1 : 0);
429 Elf* elf = ElfAllocate(mapAddress, offset, maxSize, cmd, parent, ELF_KIND_ELF, scnMax * sizeof(ElfSectionBase));
430 if (elf == nullptr) {
431 return nullptr;
432 }
433
434 ASSERT((unsigned int)scncnt == scncnt);
435 ASSERT(offsetof(Elf, state.elf32.sections) == offsetof(Elf, state.elf64.sections));
436 elf->state.elf32.sections.cnt = scncnt;
437 elf->state.elf32.sections.max = scnMax;
438
439 /* Make the class easily available. */
440 elf->binaryClass = eIdent[llvm::ELF::EI_CLASS];
441
442 if (eIdent[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) {
443 return GetElfItem<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Shdr, decltype(elf->state.elf32)>(
444 elf->state.elf32, mapAddress, eIdent, offset, maxSize, cmd, scncnt, elf);
445 } else {
446 return GetElfItem<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Shdr, decltype(elf->state.elf64)>(
447 elf->state.elf64, mapAddress, eIdent, offset, maxSize, cmd, scncnt, elf);
448 }
449 }
450
ReadMmapedFile( void* mapAddress, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent)451 ElfChecker::Elf* ElfChecker::ReadMmapedFile(
452 void* mapAddress, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent)
453 {
454 unsigned char* eIdent = reinterpret_cast<unsigned char*>(mapAddress) + offset;
455 /* See what kind of object we have here. */
456 ElfKind kind = GetElfKind(eIdent);
457 if (kind == ELF_KIND_ELF) {
458 return FileReadElf(mapAddress, eIdent, offset, maxsize, cmd, parent);
459 } else {
460 return ElfAllocate(mapAddress, offset, maxsize, cmd, parent, ELF_KIND_NONE, 0);
461 }
462 }
463
ElfMemory(char* image, size_t size)464 ElfChecker::Elf* ElfChecker::ElfMemory(char* image, size_t size)
465 {
466 if (image == nullptr) {
467 SetErrorCode(ELF_ERR_INVALID_OPERAND);
468 return nullptr;
469 }
470 return ReadMmapedFile(image, 0, size, ELF_CMD_READ, nullptr);
471 }
472
ElfRelease(Elf* elf) const473 int ElfChecker::ElfRelease(Elf* elf) const
474 {
475 if (elf == nullptr) {
476 return 0;
477 }
478 if (elf->refCount != 0) {
479 --elf->refCount;
480 if (elf->refCount != 0) {
481 int result = elf->refCount;
482 return result;
483 }
484 }
485 Elf* parent = elf->parent;
486 delete[] reinterpret_cast<char*>(elf);
487 elf = nullptr;
488 return (parent != nullptr && parent->refCount == 0 ? ElfRelease(parent) : 0);
489 }
490
~ElfChecker()491 ElfChecker::~ElfChecker()
492 {
493 if (fromMmap_ == false && elfData_ != nullptr) {
494 delete[] elfData_;
495 elfData_ = nullptr;
496 }
497 }
498 } // namespace panda::ecmascript
499