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