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