1 /*
2 * Copyright (c) 2023 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
16 #include "ecmascript/compiler/aot_file/elf_reader.h"
17
18 #include "ecmascript/base/file_header.h"
19 #include "ecmascript/ecma_macros.h"
20 #include "securec.h"
21
22 namespace panda::ecmascript {
VerifyELFHeader(uint32_t version,bool strictMatch)23 bool ElfReader::VerifyELFHeader(uint32_t version, bool strictMatch)
24 {
25 llvm::ELF::Elf64_Ehdr header = *(reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr()));
26 if (header.e_ident[llvm::ELF::EI_MAG0] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0]
27 || header.e_ident[llvm::ELF::EI_MAG1] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1]
28 || header.e_ident[llvm::ELF::EI_MAG2] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2]
29 || header.e_ident[llvm::ELF::EI_MAG3] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3]) {
30 LOG_ECMA(ERROR) << "ELF format error, expected magic is " << llvm::ELF::ElfMagic
31 << ", but got " << header.e_ident[llvm::ELF::EI_MAG0] << header.e_ident[llvm::ELF::EI_MAG1]
32 << header.e_ident[llvm::ELF::EI_MAG2] << header.e_ident[llvm::ELF::EI_MAG3];
33 return false;
34 }
35 if (!base::FileHeaderBase::VerifyVersion("Elf ", header.e_version, version, strictMatch)) {
36 return false;
37 }
38 return true;
39 }
40
GetCurModuleInfo(uint32_t i,llvm::ELF::Elf64_Off offset)41 ModuleSectionDes::ModuleRegionInfo *ElfReader::GetCurModuleInfo(uint32_t i, llvm::ELF::Elf64_Off offset)
42 {
43 uint64_t codeAddress = reinterpret_cast<uint64_t>(fileMapMem_.GetOriginAddr());
44 uint64_t info = codeAddress + offset + i * sizeof(ModuleSectionDes::ModuleRegionInfo);
45 return reinterpret_cast<ModuleSectionDes::ModuleRegionInfo *>(info);
46 }
47
ParseELFSections(ModuleSectionDes & des,std::vector<ElfSecName> & secs)48 void ElfReader::ParseELFSections(ModuleSectionDes &des, std::vector<ElfSecName> &secs)
49 {
50 llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr());
51 char *addr = reinterpret_cast<char *>(ehdr);
52 llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff);
53 ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1));
54 llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx];
55 for (size_t j = 0; j < secs.size(); ++j) {
56 int secId = -1;
57 ElfSecName sec = secs[j];
58 std::string sectionName = ModuleSectionDes::GetSecName(sec);
59 for (size_t i = 0; i < ehdr->e_shnum; ++i) {
60 llvm::ELF::Elf64_Word shName = shdr[i].sh_name;
61 char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset;
62 if (sectionName.compare(curShName) == 0) {
63 secId = static_cast<int>(i);
64 break;
65 }
66 }
67 if (secId == -1) {
68 LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab";
69 continue;
70 }
71 ASSERT(secId > 0 && secId < ehdr->e_shnum);
72 llvm::ELF::Elf64_Shdr secShdr = shdr[secId];
73 uintptr_t secAddr = reinterpret_cast<uintptr_t>(addr + secShdr.sh_offset);
74 uint32_t secSize = secShdr.sh_size;
75 if (sec == ElfSecName::ARK_FUNCENTRY) {
76 ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0));
77 }
78 if (sec == ElfSecName::ARK_STACKMAP) {
79 des.SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr));
80 des.SetArkStackMapSize(secSize);
81 } else {
82 des.SetSecAddrAndSize(sec, secAddr, secSize);
83 }
84 }
85 }
86
ParseELFSections(std::vector<ModuleSectionDes> & des,std::vector<ElfSecName> & secs)87 void ElfReader::ParseELFSections(std::vector<ModuleSectionDes> &des, std::vector<ElfSecName> &secs)
88 {
89 llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr());
90 char *addr = reinterpret_cast<char *>(ehdr);
91 llvm::ELF::Elf64_Shdr *shdrs = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff);
92 ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1));
93 llvm::ELF::Elf64_Shdr strdr = shdrs[ehdr->e_shstrndx];
94 ASSERT(ehdr->e_flags != static_cast<llvm::ELF::Elf64_Word>(-1));
95 llvm::ELF::Elf64_Shdr moduledr = shdrs[ehdr->e_flags];
96 size_t moduleInfoSize = moduledr.sh_size;
97 uint32_t moduleNum = GetModuleNum(moduleInfoSize);
98 des.resize(moduleNum);
99 std::set<ElfSecName> secSet(secs.begin(), secs.end());
100 for (ElfSecName sec : secSet) {
101 int secId = -1;
102 std::string sectionName = ModuleSectionDes::GetSecName(sec);
103 for (size_t i = 0; i < ehdr->e_shnum; ++i) {
104 llvm::ELF::Elf64_Word shName = shdrs[i].sh_name;
105 char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset;
106 if (sectionName.compare(curShName) == 0) {
107 secId = static_cast<int>(i);
108 break;
109 }
110 }
111 if (secId == -1) {
112 LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab";
113 continue;
114 }
115 ASSERT(secId > 0 && secId < ehdr->e_shnum);
116 llvm::ELF::Elf64_Shdr secShdr = shdrs[secId];
117 uintptr_t secAddr = reinterpret_cast<uintptr_t>(addr + secShdr.sh_offset);
118 uint32_t secSize = secShdr.sh_size;
119 switch (sec) {
120 case ElfSecName::TEXT: {
121 llvm::ELF::Elf64_Off secOffset = 0;
122 SeparateTextSections(des, secAddr, secOffset, moduledr.sh_offset);
123 ASSERT(static_cast<uint32_t>(secOffset) == secSize);
124 break;
125 }
126 case ElfSecName::ARK_STACKMAP: {
127 llvm::ELF::Elf64_Off secOffset = 0;
128 SeparateArkStackMapSections(des, secAddr, secOffset, moduledr.sh_offset);
129 ASSERT(static_cast<uint32_t>(secOffset) == secSize);
130 break;
131 }
132 case ElfSecName::SHSTRTAB:
133 case ElfSecName::ARK_FUNCENTRY:
134 case ElfSecName::ARK_ASMSTUB:
135 case ElfSecName::ARK_MODULEINFO: {
136 if (sec == ElfSecName::ARK_FUNCENTRY) {
137 ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0));
138 }
139 des[0].SetSecAddrAndSize(sec, secAddr, secSize);
140 break;
141 }
142 default: {
143 LOG_ECMA(FATAL) << "this section should not dump to stub file";
144 break;
145 }
146 }
147 }
148 }
149
ParseELFSections(BinaryBufferParser & parser,std::vector<ModuleSectionDes> & des,std::vector<ElfSecName> & secs)150 void ElfReader::ParseELFSections(BinaryBufferParser &parser,
151 std::vector<ModuleSectionDes> &des,
152 std::vector<ElfSecName> &secs)
153 {
154 ASSERT(des.size() == ASMSTUB_MODULE_NUM);
155 uint64_t codeAddress = reinterpret_cast<uint64_t>(stubsMem_.addr_);
156 llvm::ELF::Elf64_Ehdr ehdr;
157 parser.ParseBuffer(&ehdr, sizeof(ehdr), 0);
158 std::vector<llvm::ELF::Elf64_Shdr> shdrs(ehdr.e_shnum);
159 parser.ParseBuffer(shdrs.data(), sizeof(llvm::ELF::Elf64_Shdr) * ehdr.e_shnum, ehdr.e_shoff);
160
161 ASSERT(ehdr.e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1));
162 llvm::ELF::Elf64_Shdr strdr = shdrs[ehdr.e_shstrndx];
163 ASSERT(ehdr.e_flags != static_cast<llvm::ELF::Elf64_Word>(-1));
164 llvm::ELF::Elf64_Shdr moduledr = shdrs[ehdr.e_flags];
165 [[maybe_unused]] size_t moduleInfoSize = moduledr.sh_size;
166 uint32_t moduleNum = GetModuleNum(moduleInfoSize);
167 ASSERT(moduleNum == ASMSTUB_MODULE_NUM);
168 moduleInfo_.resize(moduleNum);
169 parser.ParseBuffer(moduleInfo_.data(), moduleInfoSize, moduledr.sh_offset);
170 std::set<ElfSecName> secSet(secs.begin(), secs.end());
171 for (ElfSecName sec : secSet) {
172 int secId = -1;
173 std::string sectionName = ModuleSectionDes::GetSecName(sec);
174 for (size_t i = 0; i < ehdr.e_shnum; ++i) {
175 llvm::ELF::Elf64_Word shName = shdrs[i].sh_name;
176 char *curShName = reinterpret_cast<char *>(parser.GetAddr()) + shName + strdr.sh_offset;
177 if (sectionName.compare(curShName) == 0) {
178 secId = static_cast<int>(i);
179 break;
180 }
181 }
182 if (secId == -1) {
183 LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab";
184 continue;
185 }
186 ASSERT(secId > 0 && secId < ehdr.e_shnum);
187 llvm::ELF::Elf64_Shdr secShdr = shdrs[secId];
188 uint64_t secAddr = static_cast<uint64_t>(codeAddress + secShdr.sh_offset);
189 uint32_t secSize = secShdr.sh_size;
190 switch (sec) {
191 case ElfSecName::TEXT: {
192 llvm::ELF::Elf64_Off secOffset = 0;
193 SeparateTextSections(parser, des, secAddr, secOffset, secShdr.sh_offset);
194 ASSERT(static_cast<uint32_t>(secOffset) == secSize);
195 break;
196 }
197 case ElfSecName::ARK_STACKMAP: {
198 llvm::ELF::Elf64_Off secOffset = 0;
199 SeparateArkStackMapSections(parser, des, secAddr, secOffset, secShdr.sh_offset);
200 ASSERT(static_cast<uint32_t>(secOffset) == secSize);
201 break;
202 }
203 case ElfSecName::SHSTRTAB:
204 case ElfSecName::ARK_FUNCENTRY:
205 case ElfSecName::ARK_ASMSTUB:
206 case ElfSecName::ARK_MODULEINFO: {
207 if (sec == ElfSecName::ARK_FUNCENTRY) {
208 ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0));
209 }
210 parser.ParseBuffer(reinterpret_cast<void *>(secAddr), secSize, secShdr.sh_offset);
211 des[0].SetSecAddrAndSize(sec, secAddr, secSize);
212 break;
213 }
214 default: {
215 LOG_ECMA(FATAL) << "this section should not dump to stub file";
216 break;
217 }
218 }
219 }
220 }
221
ParseELFSegment()222 bool ElfReader::ParseELFSegment()
223 {
224 if (fileMapMem_.GetOriginAddr() == nullptr) {
225 return false;
226 }
227 char *addr = reinterpret_cast<char *>(fileMapMem_.GetOriginAddr());
228 llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr());
229 llvm::ELF::Elf64_Phdr *phdr = reinterpret_cast<llvm::ELF::Elf64_Phdr *>(addr + ehdr->e_phoff);
230 for (int i = 0; i < ehdr->e_phnum; ++i) {
231 if (phdr[i].p_type != llvm::ELF::PT_LOAD) {
232 continue;
233 }
234 if (phdr[i].p_filesz > phdr[i].p_memsz) {
235 LOG_COMPILER(ERROR) << " p_filesz:0x" << std::hex << phdr[i].p_filesz << " > p_memsz:0x"
236 << phdr[i].p_memsz;
237 return false;
238 }
239 if (!phdr[i].p_filesz) {
240 continue;
241 }
242 unsigned char *virtualAddr = reinterpret_cast<unsigned char *>(addr + phdr[i].p_vaddr);
243 ASSERT(phdr[i].p_offset % PageSize() == 0);
244 if ((phdr[i].p_flags & llvm::ELF::PF_X) != 0) {
245 ASSERT(reinterpret_cast<uintptr_t>(virtualAddr) % PageSize() == 0);
246 PageProtect(virtualAddr, phdr[i].p_memsz, PAGE_PROT_EXEC_READ);
247 }
248 }
249 return true;
250 }
251
SeparateTextSections(std::vector<ModuleSectionDes> & des,const uintptr_t & secAddr,llvm::ELF::Elf64_Off & secOffset,const llvm::ELF::Elf64_Off & moduleInfoOffset)252 void ElfReader::SeparateTextSections(std::vector<ModuleSectionDes> &des,
253 const uintptr_t &secAddr,
254 llvm::ELF::Elf64_Off &secOffset,
255 const llvm::ELF::Elf64_Off &moduleInfoOffset)
256 {
257 for (size_t i = 0; i < des.size(); ++i) {
258 auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset);
259 secOffset = AlignUp(secOffset, AOTFileInfo::PAGE_ALIGN);
260 uint32_t rodataSize = moduleInfo->rodataSize;
261 uint32_t rodataAfterText = moduleInfo->rodataAfterText;
262 if (rodataSize > 0 && rodataAfterText == 0) {
263 des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
264 secOffset += rodataSize;
265 secOffset = AlignUp(secOffset, AOTFileInfo::TEXT_SEC_ALIGN);
266 }
267 uint32_t textSize = moduleInfo->textSize;
268 des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize);
269 secOffset += textSize;
270 if (rodataSize > 0 && rodataAfterText == 1) {
271 secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN);
272 des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
273 secOffset += rodataSize;
274 }
275 }
276 }
277
SeparateArkStackMapSections(std::vector<ModuleSectionDes> & des,const uintptr_t & secAddr,llvm::ELF::Elf64_Off & secOffset,const llvm::ELF::Elf64_Off & moduleInfoOffset)278 void ElfReader::SeparateArkStackMapSections(std::vector<ModuleSectionDes> &des,
279 const uintptr_t &secAddr,
280 llvm::ELF::Elf64_Off &secOffset,
281 const llvm::ELF::Elf64_Off &moduleInfoOffset)
282 {
283 for (size_t i = 0; i < des.size(); ++i) {
284 auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset);
285 uint32_t stackMapSize = moduleInfo->stackMapSize;
286 des[i].SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr + secOffset));
287 des[i].SetArkStackMapSize(stackMapSize);
288 uint32_t index = moduleInfo->startIndex;
289 uint32_t cnt = moduleInfo->funcCount;
290 des[i].SetStartIndex(index);
291 des[i].SetFuncCount(cnt);
292 secOffset += stackMapSize;
293 }
294 }
295
SeparateTextSections(BinaryBufferParser & parser,std::vector<ModuleSectionDes> & des,const uint64_t & secAddr,llvm::ELF::Elf64_Off & secOffset,const llvm::ELF::Elf64_Off & curShOffset)296 void ElfReader::SeparateTextSections(BinaryBufferParser &parser,
297 std::vector<ModuleSectionDes> &des,
298 const uint64_t &secAddr,
299 llvm::ELF::Elf64_Off &secOffset,
300 const llvm::ELF::Elf64_Off &curShOffset)
301 {
302 for (size_t i = 0; i < des.size(); ++i) {
303 auto moduleInfo = moduleInfo_[i];
304 secOffset = AlignUp(secOffset, AOTFileInfo::PAGE_ALIGN);
305 uint32_t rodataSize = moduleInfo.rodataSize;
306 uint32_t rodataAfterText = moduleInfo.rodataAfterText;
307 if (rodataSize > 0 && rodataAfterText == 0) {
308 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), rodataSize, curShOffset + secOffset);
309 des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
310 secOffset += rodataSize;
311 secOffset = AlignUp(secOffset, AOTFileInfo::TEXT_SEC_ALIGN);
312 }
313 uint32_t textSize = moduleInfo.textSize;
314 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), textSize, curShOffset + secOffset);
315 des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize);
316 secOffset += textSize;
317 if (rodataSize > 0 && rodataAfterText == 1) {
318 secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN);
319 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), rodataSize, curShOffset + secOffset);
320 des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
321 secOffset += rodataSize;
322 }
323 }
324 }
325
SeparateArkStackMapSections(BinaryBufferParser & parser,std::vector<ModuleSectionDes> & des,const uint64_t & secAddr,llvm::ELF::Elf64_Off & secOffset,const llvm::ELF::Elf64_Off & curShOffset)326 void ElfReader::SeparateArkStackMapSections(BinaryBufferParser &parser,
327 std::vector<ModuleSectionDes> &des,
328 const uint64_t &secAddr,
329 llvm::ELF::Elf64_Off &secOffset,
330 const llvm::ELF::Elf64_Off &curShOffset)
331 {
332 for (size_t i = 0; i < des.size(); ++i) {
333 auto moduleInfo = moduleInfo_[i];
334 uint32_t stackMapSize = moduleInfo.stackMapSize;
335 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), stackMapSize, curShOffset + secOffset);
336 des[i].SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr + secOffset));
337 des[i].SetArkStackMapSize(stackMapSize);
338 uint32_t index = moduleInfo.startIndex;
339 uint32_t cnt = moduleInfo.funcCount;
340 des[i].SetStartIndex(index);
341 des[i].SetFuncCount(cnt);
342 secOffset += stackMapSize;
343 }
344 }
345 } // namespace panda::ecmascript