• 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 #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