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