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