mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
ELF format standardized AOT file
Signed-off-by: wuzhangda <wuzhangda@huawei.com> Change-Id: Ibfb512c6b86ac1ab103339c6e1043b56e9c6b612
This commit is contained in:
parent
f12a7e338f
commit
c05de1f0a0
52
BUILD.gn
52
BUILD.gn
@ -559,6 +559,8 @@ ecma_source = [
|
||||
"ecmascript/builtins/builtins_weak_ref.cpp",
|
||||
"ecmascript/builtins/builtins_weak_set.cpp",
|
||||
"ecmascript/byte_array.cpp",
|
||||
"ecmascript/compiler/aot_file/elf_builder.cpp",
|
||||
"ecmascript/compiler/aot_file/elf_reader.cpp",
|
||||
"ecmascript/containers/containers_arraylist.cpp",
|
||||
"ecmascript/containers/containers_deque.cpp",
|
||||
"ecmascript/containers/containers_errors.cpp",
|
||||
@ -799,9 +801,49 @@ ecma_profiler_source += [
|
||||
ecma_platform_source = []
|
||||
|
||||
ecma_platform_source += [ "ecmascript/platform/common/map.cpp" ]
|
||||
|
||||
config("include_llvm") {
|
||||
if (compile_llvm_online) {
|
||||
include_dirs = [
|
||||
"//third_party/third_party_llvm-project/build/include",
|
||||
"//third_party/third_party_llvm-project/llvm/include/",
|
||||
]
|
||||
} else {
|
||||
if (is_mingw) {
|
||||
include_dirs = [
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_windows/llvm/include",
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_windows/build/include",
|
||||
]
|
||||
} else if (is_mac) {
|
||||
if (host_cpu == "arm64") {
|
||||
include_dirs = [
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_darwin_arm64/llvm/include",
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_darwin_arm64/build/include",
|
||||
]
|
||||
} else {
|
||||
include_dirs = [
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_darwin_x64/llvm/include",
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_darwin_x64/build/include",
|
||||
]
|
||||
}
|
||||
} else {
|
||||
if (current_cpu == "arm64") {
|
||||
include_dirs = [
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_aarch64/llvm/include",
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts_aarch64/build/include",
|
||||
]
|
||||
} else {
|
||||
include_dirs = [
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/llvm/include",
|
||||
"//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/include",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_mingw) {
|
||||
ecma_platform_source += [
|
||||
"ecmascript/platform/common/elf.cpp",
|
||||
"ecmascript/platform/windows/backtrace.cpp",
|
||||
"ecmascript/platform/windows/map.cpp",
|
||||
"ecmascript/platform/windows/file.cpp",
|
||||
@ -816,7 +858,6 @@ if (is_mingw) {
|
||||
]
|
||||
if (is_mac || target_os == "ios") {
|
||||
ecma_platform_source += [
|
||||
"ecmascript/platform/common/elf.cpp",
|
||||
"ecmascript/platform/unix/mac/os.cpp",
|
||||
"ecmascript/platform/unix/mac/backtrace.cpp",
|
||||
]
|
||||
@ -824,13 +865,11 @@ if (is_mingw) {
|
||||
ecma_platform_source += [
|
||||
"ecmascript/platform/unix/linux/os.cpp",
|
||||
"ecmascript/platform/unix/ohos/backtrace.cpp",
|
||||
"ecmascript/platform/unix/elf.cpp",
|
||||
]
|
||||
} else if (is_linux) {
|
||||
ecma_platform_source += [
|
||||
"ecmascript/platform/unix/linux/os.cpp",
|
||||
"ecmascript/platform/unix/linux/backtrace.cpp",
|
||||
"ecmascript/platform/unix/elf.cpp",
|
||||
]
|
||||
} else {
|
||||
print("Invalid os!")
|
||||
@ -846,6 +885,7 @@ ohos_source_set("libark_jsruntime_set") {
|
||||
sources += ecma_platform_source
|
||||
|
||||
public_configs = [ "$js_root:ark_jsruntime_public_config" ]
|
||||
public_configs += [ ":include_llvm" ]
|
||||
|
||||
configs = [
|
||||
"$js_root:ark_jsruntime_common_config",
|
||||
@ -920,6 +960,7 @@ ohos_source_set("libark_jsruntime_test_set") {
|
||||
}
|
||||
|
||||
public_configs = [ "$js_root:ark_jsruntime_public_config" ]
|
||||
public_configs += [ ":include_llvm" ]
|
||||
|
||||
configs = [
|
||||
"$js_root:ark_jsruntime_common_config",
|
||||
@ -1007,6 +1048,9 @@ ohos_shared_library("libark_jsruntime_test") {
|
||||
"$ark_root/libpandafile:libarkfile_static",
|
||||
]
|
||||
|
||||
public_configs = [ "$js_root:ark_jsruntime_public_config" ]
|
||||
public_configs += [ ":include_llvm" ]
|
||||
|
||||
ldflags = []
|
||||
if (enable_coverage) {
|
||||
ldflags += [ "--coverage" ]
|
||||
|
@ -13,8 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "ecmascript/aot_file_manager.h"
|
||||
|
||||
#include "ecmascript/base/config.h"
|
||||
#include "ecmascript/compiler/aot_file/elf_builder.h"
|
||||
#include "ecmascript/compiler/aot_file/elf_reader.h"
|
||||
#include "ecmascript/compiler/bc_call_signature.h"
|
||||
#include "ecmascript/compiler/common_stubs.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
@ -31,9 +32,6 @@
|
||||
#include "ecmascript/stackmap/ark_stackmap_parser.h"
|
||||
#include "ecmascript/stackmap/llvm_stackmap_parser.h"
|
||||
#include "ecmascript/mem/region.h"
|
||||
#include "ecmascript/platform/elf.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
#include "ecmascript/platform/map.h"
|
||||
|
||||
|
||||
extern const uint8_t _binary_stub_an_start[];
|
||||
@ -199,8 +197,8 @@ bool StubFileInfo::Load()
|
||||
return false;
|
||||
}
|
||||
|
||||
ExecutedMemoryAllocator::AllocateBuf(totalCodeSize_, exeMem_);
|
||||
uint64_t codeAddress = reinterpret_cast<uint64_t>(exeMem_.addr_);
|
||||
ExecutedMemoryAllocator::AllocateBuf(totalCodeSize_, stubsMem_);
|
||||
uint64_t codeAddress = reinterpret_cast<uint64_t>(stubsMem_.addr_);
|
||||
uint32_t curUnitOffset = 0;
|
||||
uint32_t asmStubSize = 0;
|
||||
binBufparser.ParseBuffer(&asmStubSize, sizeof(asmStubSize));
|
||||
@ -223,7 +221,7 @@ bool StubFileInfo::Load()
|
||||
}
|
||||
}
|
||||
LOG_COMPILER(INFO) << "loaded stub file successfully";
|
||||
PageProtect(exeMem_.addr_, exeMem_.size_, PAGE_PROT_EXEC_READ);
|
||||
PageProtect(stubsMem_.addr_, stubsMem_.size_, PAGE_PROT_EXEC_READ);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -246,7 +244,7 @@ void StubFileInfo::Dump() const
|
||||
}
|
||||
}
|
||||
|
||||
void AnFileInfo::Save(const std::string &filename, kungfu::Triple triple)
|
||||
void AnFileInfo::Save(const std::string &filename, Triple triple)
|
||||
{
|
||||
std::string realPath;
|
||||
if (!RealPath(filename, realPath, false)) {
|
||||
@ -260,20 +258,21 @@ void AnFileInfo::Save(const std::string &filename, kungfu::Triple triple)
|
||||
}
|
||||
|
||||
std::ofstream file(realPath.c_str(), std::ofstream::binary);
|
||||
SetStubNum(entries_.size());
|
||||
ASSERT(GetCodeUnitsNum() == 1);
|
||||
ModuleSectionDes &des = des_[0];
|
||||
// add section
|
||||
uint64_t addr = reinterpret_cast<uint64_t>(entries_.data());
|
||||
entryNum_ = entries_.size();
|
||||
uint32_t size = sizeof(FuncEntryDes) * entryNum_;
|
||||
des.SetSecAddr(addr, ElfSecName::ARK_FUNCENTRY);
|
||||
des.SetSecSize(size, ElfSecName::ARK_FUNCENTRY);
|
||||
|
||||
Elf64_Ehdr header;
|
||||
PackELFHeader(header, AOTFileManager::AOT_VERSION, triple);
|
||||
file.write(reinterpret_cast<char *>(&header), sizeof(Elf64_Ehdr));
|
||||
file.write(reinterpret_cast<char *>(&entryNum_), sizeof(entryNum_));
|
||||
file.write(reinterpret_cast<char *>(entries_.data()), sizeof(FuncEntryDes) * entryNum_);
|
||||
uint32_t moduleNum = GetCodeUnitsNum();
|
||||
file.write(reinterpret_cast<char *>(&moduleNum), sizeof(moduleNum_));
|
||||
file.write(reinterpret_cast<char *>(&totalCodeSize_), sizeof(totalCodeSize_));
|
||||
LOG_COMPILER(DEBUG) << "total code size = " << (totalCodeSize_ / 1_KB) << "KB";
|
||||
for (size_t i = 0; i < moduleNum; i++) {
|
||||
des_[i].SaveSectionsInfo(file);
|
||||
}
|
||||
ElfBuilder builder(des);
|
||||
llvm::ELF::Elf64_Ehdr header;
|
||||
builder.PackELFHeader(header, AOTFileManager::AOT_VERSION, triple);
|
||||
file.write(reinterpret_cast<char *>(&header), sizeof(llvm::ELF::Elf64_Shdr));
|
||||
builder.PackELFSections(file);
|
||||
builder.PackELFSegment(file);
|
||||
file.close();
|
||||
}
|
||||
|
||||
@ -287,39 +286,37 @@ bool AnFileInfo::Load(const std::string &filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ifstream file(realPath.c_str(), std::ofstream::binary);
|
||||
if (!file.good()) {
|
||||
LOG_COMPILER(INFO) << "Fail to load an file: " << realPath.c_str();
|
||||
file.close();
|
||||
fileMapMem_ = FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ);
|
||||
|
||||
if (fileMapMem_.GetOriginAddr() == nullptr) {
|
||||
LOG_ECMA(ERROR) << "File mmap failed";
|
||||
return false;
|
||||
}
|
||||
PagePreRead(fileMapMem_.GetOriginAddr(), fileMapMem_.GetSize());
|
||||
|
||||
Elf64_Ehdr header;
|
||||
file.read(reinterpret_cast<char *>(&header), sizeof(Elf64_Ehdr));
|
||||
if (!VerifyELFHeader(header, AOTFileManager::AOT_VERSION)) {
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
file.read(reinterpret_cast<char *>(&entryNum_), sizeof(entryNum_));
|
||||
entries_.resize(entryNum_);
|
||||
file.read(reinterpret_cast<char *>(entries_.data()), sizeof(FuncEntryDes) * entryNum_);
|
||||
file.read(reinterpret_cast<char *>(&moduleNum_), sizeof(moduleNum_));
|
||||
moduleNum_ = 1;
|
||||
des_.resize(moduleNum_);
|
||||
file.read(reinterpret_cast<char *>(&totalCodeSize_), sizeof(totalCodeSize_));
|
||||
ModuleSectionDes &des = des_[0];
|
||||
|
||||
if (totalCodeSize_ == 0) {
|
||||
file.close();
|
||||
LOG_COMPILER(ERROR) << "error: code in the an file is empty!";
|
||||
ElfReader reader(fileMapMem_);
|
||||
std::vector<ElfSecName> secs = GetDumpSectionNames();
|
||||
if (!reader.VerifyELFHeader(AOTFileManager::AOT_VERSION)) {
|
||||
return false;
|
||||
}
|
||||
ExecutedMemoryAllocator::AllocateBuf(totalCodeSize_, exeMem_);
|
||||
uint64_t codeAddress = reinterpret_cast<uint64_t>(exeMem_.addr_);
|
||||
uint32_t curUnitOffset = 0;
|
||||
for (size_t i = 0; i < moduleNum_; i++) {
|
||||
des_[i].LoadSectionsInfo(file, curUnitOffset, codeAddress);
|
||||
reader.ParseELFSections(des, secs);
|
||||
if (!reader.ParseELFSegment()) {
|
||||
LOG_ECMA(ERROR) << "modify mmap area permission failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t secAddr = des.GetSecAddr(ElfSecName::ARK_FUNCENTRY);
|
||||
uint32_t secSize = des.GetSecSize(ElfSecName::ARK_FUNCENTRY);
|
||||
FuncEntryDes *entryDes = reinterpret_cast<FuncEntryDes *>(secAddr);
|
||||
entryNum_ = secSize / sizeof(FuncEntryDes);
|
||||
entries_.assign(entryDes, entryDes + entryNum_);
|
||||
des.SetStartIndex(0);
|
||||
des.SetFuncCount(entryNum_);
|
||||
|
||||
size_t len = entries_.size();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
FuncEntryDes& funcDes = entries_[i];
|
||||
@ -336,10 +333,16 @@ bool AnFileInfo::Load(const std::string &filename)
|
||||
|
||||
LOG_COMPILER(INFO) << "loaded an file: " << filename.c_str();
|
||||
isLoad_ = true;
|
||||
PageProtect(exeMem_.addr_, exeMem_.size_, PAGE_PROT_EXEC_READ);
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<ElfSecName> & AnFileInfo::GetDumpSectionNames()
|
||||
{
|
||||
static const std::vector<ElfSecName> secNames = {ElfSecName::RODATA_CST8, ElfSecName::TEXT, ElfSecName::STRTAB,
|
||||
ElfSecName::SYMTAB, ElfSecName::ARK_STACKMAP, ElfSecName::ARK_FUNCENTRY};
|
||||
return secNames;
|
||||
}
|
||||
|
||||
void AnFileInfo::Dump() const
|
||||
{
|
||||
LOG_COMPILER(ERROR) << "An file loading: ";
|
||||
@ -819,16 +822,24 @@ AnFileDataManager::~AnFileDataManager()
|
||||
SafeDestoryAllData();
|
||||
}
|
||||
|
||||
void AnFileDataManager::DestoryFileMapMem(MemMap &fileMapMem)
|
||||
{
|
||||
if (fileMapMem.GetOriginAddr() != nullptr && fileMapMem.GetSize() > 0) {
|
||||
FileUnMap(fileMapMem);
|
||||
fileMapMem.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void AnFileDataManager::SafeDestoryAllData()
|
||||
{
|
||||
os::memory::WriteLockHolder lock(lock_);
|
||||
if (loadedStub_ != nullptr) {
|
||||
ExecutedMemoryAllocator::DestoryBuf(loadedStub_->GetExeMem());
|
||||
ExecutedMemoryAllocator::DestoryBuf(loadedStub_->GetStubsMem());
|
||||
loadedStub_ = nullptr;
|
||||
}
|
||||
|
||||
for (auto &iter : loadedAn_) {
|
||||
ExecutedMemoryAllocator::DestoryBuf(iter->GetExeMem());
|
||||
DestoryFileMapMem(iter->GetFileMapMem());
|
||||
}
|
||||
loadedAn_.clear();
|
||||
}
|
||||
|
@ -15,11 +15,14 @@
|
||||
#ifndef ECMASCRIPT_AOT_FILE_MANAGER_H
|
||||
#define ECMASCRIPT_AOT_FILE_MANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include "ecmascript/compiler/binary_section.h"
|
||||
#include "ecmascript/deoptimizer/calleeReg.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_runtime_options.h"
|
||||
#include "ecmascript/stackmap/ark_stackmap.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
#include "ecmascript/platform/map.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JSpandafile;
|
||||
@ -66,33 +69,37 @@ struct ModuleSectionDes {
|
||||
uint32_t arkStackMapSize_ {0};
|
||||
uint8_t *arkStackMapRawPtr_ {nullptr};
|
||||
|
||||
std::string GetSecName(const ElfSecName idx) const
|
||||
static std::string GetSecName(const ElfSecName idx)
|
||||
{
|
||||
switch (idx) {
|
||||
case ElfSecName::RODATA:
|
||||
return "rodata";
|
||||
return ".rodata";
|
||||
case ElfSecName::RODATA_CST4:
|
||||
return "rodata.cst4";
|
||||
return ".rodata.cst4";
|
||||
case ElfSecName::RODATA_CST8:
|
||||
return "rodata.cst8";
|
||||
return ".rodata.cst8";
|
||||
case ElfSecName::RODATA_CST16:
|
||||
return "rodata.cst16";
|
||||
return ".rodata.cst16";
|
||||
case ElfSecName::RODATA_CST32:
|
||||
return "rodata.cst32";
|
||||
return ".rodata.cst32";
|
||||
case ElfSecName::TEXT:
|
||||
return "text";
|
||||
return ".text";
|
||||
case ElfSecName::DATA:
|
||||
return "data";
|
||||
return ".data";
|
||||
case ElfSecName::GOT:
|
||||
return "got";
|
||||
return ".got";
|
||||
case ElfSecName::RELATEXT:
|
||||
return "rela.text";
|
||||
return ".rela.text";
|
||||
case ElfSecName::STRTAB:
|
||||
return "strtab";
|
||||
return ".strtab";
|
||||
case ElfSecName::SYMTAB:
|
||||
return "symtab";
|
||||
return ".symtab";
|
||||
case ElfSecName::LLVM_STACKMAP:
|
||||
return "llvm_stackmaps";
|
||||
return ".llvm_stackmaps";
|
||||
case ElfSecName::ARK_STACKMAP:
|
||||
return ".ark_stackmaps";
|
||||
case ElfSecName::ARK_FUNCENTRY:
|
||||
return ".ark_funcentry";
|
||||
default: {
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
@ -110,6 +117,11 @@ struct ModuleSectionDes {
|
||||
return std::move(arkStackMapPtr_);
|
||||
}
|
||||
|
||||
std::shared_ptr<uint8_t> GetArkStackMapSharePtr() const
|
||||
{
|
||||
return std::move(arkStackMapPtr_);
|
||||
}
|
||||
|
||||
void SetArkStackMapPtr(uint8_t *ptr)
|
||||
{
|
||||
arkStackMapRawPtr_ = ptr;
|
||||
@ -331,8 +343,12 @@ public:
|
||||
bool CalCallSiteInfo(uintptr_t retAddr, CallSiteInfo& ret) const;
|
||||
|
||||
protected:
|
||||
ExecutedMemoryAllocator::ExeMem& GetExeMem() {
|
||||
return exeMem_;
|
||||
ExecutedMemoryAllocator::ExeMem& GetStubsMem() {
|
||||
return stubsMem_;
|
||||
}
|
||||
|
||||
MemMap& GetFileMapMem() {
|
||||
return fileMapMem_;
|
||||
}
|
||||
|
||||
uint32_t entryNum_ {0};
|
||||
@ -340,14 +356,15 @@ protected:
|
||||
uint32_t totalCodeSize_ {0};
|
||||
std::vector<FuncEntryDes> entries_ {};
|
||||
std::vector<ModuleSectionDes> des_ {};
|
||||
ExecutedMemoryAllocator::ExeMem exeMem_ {};
|
||||
ExecutedMemoryAllocator::ExeMem stubsMem_ {};
|
||||
MemMap fileMapMem_ {};
|
||||
};
|
||||
|
||||
class PUBLIC_API AnFileInfo : public AOTFileInfo {
|
||||
public:
|
||||
AnFileInfo() = default;
|
||||
~AnFileInfo() override = default;
|
||||
void Save(const std::string &filename, kungfu::Triple triple);
|
||||
void Save(const std::string &filename, Triple triple);
|
||||
void AddModuleDes(ModuleSectionDes &moduleDes)
|
||||
{
|
||||
des_.emplace_back(moduleDes);
|
||||
@ -380,7 +397,7 @@ public:
|
||||
|
||||
private:
|
||||
bool Load(const std::string &filename);
|
||||
void RewriteRelcateTextSection(const char* symbol, uintptr_t patchAddr);
|
||||
const std::vector<ElfSecName> & GetDumpSectionNames();
|
||||
std::unordered_map<uint32_t, uint64_t> mainEntryMap_ {};
|
||||
bool isLoad_ {false};
|
||||
|
||||
@ -479,6 +496,7 @@ public:
|
||||
bool SafeInsideStub(uintptr_t pc);
|
||||
bool SafeInsideAOT(uintptr_t pc);
|
||||
AOTFileInfo::CallSiteInfo SafeCalCallSiteInfo(uintptr_t retAddr);
|
||||
void DestoryFileMapMem(MemMap &fileMapMem);
|
||||
void SafeDestoryAllData();
|
||||
const std::string& GetDir() const
|
||||
{
|
||||
@ -524,7 +542,7 @@ public:
|
||||
explicit AOTFileManager(EcmaVM *vm);
|
||||
virtual ~AOTFileManager();
|
||||
|
||||
static constexpr uint32_t AOT_VERSION = 1;
|
||||
static constexpr uint32_t AOT_VERSION = 2;
|
||||
static constexpr char FILE_EXTENSION_AN[] = ".an";
|
||||
static constexpr char FILE_EXTENSION_AI[] = ".ai";
|
||||
static constexpr uint8_t DESERI_CP_ITEM_SIZE = 2;
|
||||
|
496
ecmascript/compiler/aot_file/elf_builder.cpp
Normal file
496
ecmascript/compiler/aot_file/elf_builder.cpp
Normal file
@ -0,0 +1,496 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/aot_file/elf_builder.h"
|
||||
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void ElfBuilder::ModifyStrTabSection()
|
||||
{
|
||||
bool existedStrTab = false;
|
||||
uint64_t strTabAddr = 0;
|
||||
uint32_t strTabSize = 0;
|
||||
std::vector<std::string> sectionNames;
|
||||
std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
// modify strtab
|
||||
for (auto &s : sections) {
|
||||
if (s.first == ElfSecName::STRTAB) {
|
||||
existedStrTab = true;
|
||||
strTabAddr = s.second.first;
|
||||
strTabSize = s.second.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &s : sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
auto str = sectionDes_.GetSecName(s.first);
|
||||
llvm::ELF::Elf64_Word id = FindShName(str, strTabAddr, strTabSize);
|
||||
if (id == static_cast<llvm::ELF::Elf64_Word>(-1)) {
|
||||
sectionNames.emplace_back(str);
|
||||
}
|
||||
}
|
||||
uint32_t size = 0;
|
||||
if (existedStrTab) {
|
||||
size += strTabSize;
|
||||
}
|
||||
for (auto &str: sectionNames) {
|
||||
size = size + str.size() + 1;
|
||||
}
|
||||
strTabPtr_ = std::make_unique<char []>(size);
|
||||
char *dst = strTabPtr_.get();
|
||||
if (strTabSize > 0) {
|
||||
if ((memcpy_s(dst, size, reinterpret_cast<char *>(strTabAddr), strTabSize)) != EOK) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
uint32_t i = strTabSize;
|
||||
for (auto &str: sectionNames) {
|
||||
uint32_t copySize = str.size();
|
||||
if (copySize == 0) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
if ((copySize != 0) && ((memcpy_s(dst + i, size - i + 1, str.data(), copySize)) != EOK)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
dst[i + copySize] = 0x0;
|
||||
i = i + copySize + 1;
|
||||
}
|
||||
|
||||
if (existedStrTab) {
|
||||
sections.erase(ElfSecName::STRTAB);
|
||||
}
|
||||
sections[ElfSecName::STRTAB] = std::make_pair(reinterpret_cast<uint64_t>(strTabPtr_.get()), size);
|
||||
[[maybe_unused]] uint32_t symtabSize = sections[ElfSecName::SYMTAB].second;
|
||||
ASSERT(symtabSize % sizeof(llvm::ELF::Elf64_Sym) == 0);
|
||||
if (enableSecDump_) {
|
||||
DumpSection();
|
||||
}
|
||||
}
|
||||
|
||||
void ElfBuilder::DumpSection() const
|
||||
{
|
||||
const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
// dump
|
||||
for (auto &s : sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
LOG_COMPILER(INFO) << "secname :" << std::dec << static_cast<int>(s.first)
|
||||
<< " addr:0x" << std::hex << s.second.first << " size:0x" << s.second.second << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void ElfBuilder::AddArkStackMapSection()
|
||||
{
|
||||
// add arkstackmap
|
||||
std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
std::shared_ptr<uint8_t> ptr = sectionDes_.GetArkStackMapSharePtr();
|
||||
uint64_t arkStackMapAddr = reinterpret_cast<uint64_t>(ptr.get());
|
||||
uint32_t arkStackMapSize = sectionDes_.arkStackMapSize_;
|
||||
if (arkStackMapSize > 0) {
|
||||
sections[ElfSecName::ARK_STACKMAP] = std::pair(arkStackMapAddr, arkStackMapSize);
|
||||
}
|
||||
}
|
||||
|
||||
ElfBuilder::ElfBuilder(ModuleSectionDes sectionDes): sectionDes_(sectionDes)
|
||||
{
|
||||
AddArkStackMapSection();
|
||||
ModifyStrTabSection();
|
||||
sectionToAlign_ = {
|
||||
{ElfSecName::RODATA, 8},
|
||||
{ElfSecName::RODATA_CST4, 8},
|
||||
{ElfSecName::RODATA_CST8, 8},
|
||||
{ElfSecName::RODATA_CST16, 8},
|
||||
{ElfSecName::RODATA_CST32, 8},
|
||||
{ElfSecName::TEXT, 16},
|
||||
{ElfSecName::STRTAB, 1},
|
||||
{ElfSecName::SYMTAB, 8},
|
||||
{ElfSecName::ARK_STACKMAP, 8},
|
||||
{ElfSecName::ARK_FUNCENTRY, 8},
|
||||
};
|
||||
|
||||
sectionToSegment_ = {
|
||||
{ElfSecName::RODATA, ElfSecName::TEXT},
|
||||
{ElfSecName::RODATA_CST4, ElfSecName::TEXT},
|
||||
{ElfSecName::RODATA_CST8, ElfSecName::TEXT},
|
||||
{ElfSecName::RODATA_CST16, ElfSecName::TEXT},
|
||||
{ElfSecName::RODATA_CST32, ElfSecName::TEXT},
|
||||
{ElfSecName::TEXT, ElfSecName::TEXT},
|
||||
{ElfSecName::STRTAB, ElfSecName::DATA},
|
||||
{ElfSecName::SYMTAB, ElfSecName::DATA},
|
||||
{ElfSecName::ARK_STACKMAP, ElfSecName::DATA},
|
||||
{ElfSecName::ARK_FUNCENTRY, ElfSecName::DATA},
|
||||
};
|
||||
|
||||
segmentToFlag_ = {
|
||||
{ElfSecName::TEXT, llvm::ELF::PF_X | llvm::ELF::PF_R},
|
||||
{ElfSecName::DATA, llvm::ELF::PF_R},
|
||||
};
|
||||
}
|
||||
|
||||
ElfBuilder::~ElfBuilder()
|
||||
{
|
||||
strTabPtr_ = nullptr;
|
||||
}
|
||||
|
||||
llvm::ELF::Elf64_Half ElfBuilder::GetShStrNdx(std::map<ElfSecName, std::pair<uint64_t, uint32_t>>& sections) const
|
||||
{
|
||||
llvm::ELF::Elf64_Half shstrndx = 1; // skip null section
|
||||
for (auto &s : sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
if (s.first == ElfSecName::STRTAB) {
|
||||
return shstrndx;
|
||||
}
|
||||
shstrndx++;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
llvm::ELF::Elf64_Half ElfBuilder::GetSecSize() const
|
||||
{
|
||||
llvm::ELF::Elf64_Half secsSize = 0;
|
||||
const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
for (auto &s : sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
uint32_t curSecSize = sectionDes_.GetSecSize(s.first);
|
||||
secsSize += curSecSize;
|
||||
}
|
||||
return secsSize;
|
||||
}
|
||||
|
||||
int ElfBuilder::GetSecNum() const
|
||||
{
|
||||
int secNum = 0;
|
||||
const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
for (auto &s : sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
++secNum;
|
||||
}
|
||||
return secNum;
|
||||
}
|
||||
|
||||
/*
|
||||
ELF Header as follow:
|
||||
ELF Header:
|
||||
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
|
||||
Class: ELF64
|
||||
Data: 2's complement, little endian
|
||||
Version: 1
|
||||
OS/ABI: UNIX - System V
|
||||
ABI Version: 0
|
||||
Type: DYN (Shared object file)
|
||||
Machine: Advanced Micro Devices X86-64
|
||||
Version: 0x2
|
||||
Entry point address: 0x0
|
||||
Start of program headers: 20480 (bytes into file)
|
||||
Start of section headers: 64 (bytes into file)
|
||||
Flags: 0x0
|
||||
Size of this header: 64 (bytes)
|
||||
Size of program headers: 56 (bytes)
|
||||
Number of program headers: 2
|
||||
Size of section headers: 64 (bytes)
|
||||
Number of section headers: 7
|
||||
Section header string table index: 3
|
||||
There are 7 section headers, starting at offset 0x40:
|
||||
*/
|
||||
void ElfBuilder::PackELFHeader(llvm::ELF::Elf64_Ehdr &header, uint32_t version, Triple triple)
|
||||
{
|
||||
if (memset_s(reinterpret_cast<void *>(&header), sizeof(llvm::ELF::Elf64_Ehdr), 0, sizeof(llvm::ELF::Elf64_Ehdr)) != EOK) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
header.e_ident[llvm::ELF::EI_MAG0] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0];
|
||||
header.e_ident[llvm::ELF::EI_MAG1] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1];
|
||||
header.e_ident[llvm::ELF::EI_MAG2] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2];
|
||||
header.e_ident[llvm::ELF::EI_MAG3] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3];
|
||||
header.e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;
|
||||
header.e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;
|
||||
header.e_ident[llvm::ELF::EI_VERSION] = 1;
|
||||
|
||||
header.e_type = llvm::ELF::ET_DYN;
|
||||
switch (triple) {
|
||||
case Triple::TRIPLE_AMD64:
|
||||
header.e_machine = llvm::ELF::EM_X86_64;
|
||||
break;
|
||||
case Triple::TRIPLE_ARM32:
|
||||
header.e_machine = llvm::ELF::EM_ARM;
|
||||
break;
|
||||
case Triple::TRIPLE_AARCH64:
|
||||
header.e_machine = llvm::ELF::EM_AARCH64;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
header.e_version = version;
|
||||
std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
// start of section headers
|
||||
header.e_shoff = sizeof(llvm::ELF::Elf64_Ehdr);
|
||||
// size of ehdr
|
||||
header.e_ehsize = sizeof(llvm::ELF::Elf64_Ehdr);
|
||||
// size of section headers
|
||||
header.e_shentsize = sizeof(llvm::ELF::Elf64_Shdr);
|
||||
// number of section headers
|
||||
header.e_shnum = GetSecNum() + 1; // 1: skip null section and ark stackmap
|
||||
// section header string table index
|
||||
header.e_shstrndx = GetShStrNdx(sections);
|
||||
// phr
|
||||
header.e_phentsize = sizeof(llvm::ELF::Elf64_Phdr);
|
||||
header.e_phnum = GetSegmentNum();
|
||||
}
|
||||
|
||||
int ElfBuilder::GetSegmentNum() const
|
||||
{
|
||||
const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
std::set<ElfSecName> segments;
|
||||
for (auto &s: sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
auto it = sectionToSegment_.find(s.first);
|
||||
ASSERT(it != sectionToSegment_.end());
|
||||
ElfSecName name = it->second;
|
||||
segments.insert(name);
|
||||
}
|
||||
return segments.size();
|
||||
}
|
||||
|
||||
ElfSecName ElfBuilder::FindLastSection(ElfSecName segment) const
|
||||
{
|
||||
ElfSecName ans = ElfSecName::NONE;
|
||||
const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
for (auto &s: sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
auto it = sectionToSegment_.find(s.first);
|
||||
ASSERT(it != sectionToSegment_.end());
|
||||
ElfSecName name = it->second;
|
||||
if (name != segment) {
|
||||
continue;
|
||||
}
|
||||
ans = std::max(ans, s.first);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
llvm::ELF::Elf64_Word ElfBuilder::FindShName(std::string name, uintptr_t strTabPtr, int strTabSize)
|
||||
{
|
||||
llvm::ELF::Elf64_Word ans = -1;
|
||||
int len = name.size();
|
||||
if (strTabSize < len + 1) {
|
||||
return ans;
|
||||
}
|
||||
LOG_ECMA(DEBUG) << " FindShName name:" << name.c_str() << std::endl;
|
||||
for (int i = 0; i < strTabSize - len + 1; ++i) {
|
||||
char *dst = reinterpret_cast<char *>(strTabPtr) + i;
|
||||
if (name.compare(dst) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint32_t> ElfBuilder::FindStrTab() const
|
||||
{
|
||||
const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
uint64_t strTabAddr = 0;
|
||||
uint32_t strTabSize = 0;
|
||||
for (auto &s: sections) {
|
||||
uint32_t curSecSize = sectionDes_.GetSecSize(s.first);
|
||||
uint64_t curSecAddr = sectionDes_.GetSecAddr(s.first);
|
||||
if (s.first == ElfSecName::STRTAB) {
|
||||
strTabSize = curSecSize;
|
||||
strTabAddr = curSecAddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::make_pair(strTabAddr, strTabSize);
|
||||
}
|
||||
|
||||
/*
|
||||
section layout as follows:
|
||||
Section Headers:
|
||||
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
|
||||
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
|
||||
[ 1] .rodata.cst8 PROGBITS 0000000000001000 001000 000020 00 AM 0 0 8
|
||||
[ 2] .text PROGBITS 0000000000001020 001020 001130 00 AX 0 0 16
|
||||
[ 3] .strtab STRTAB 0000000000003000 003000 0001a5 00 A 0 0 1
|
||||
[ 4] .symtab SYMTAB 00000000000031a8 0031a8 0001c8 18 A 1 0 8
|
||||
[ 5] .ark_funcentry PROGBITS 0000000000003370 003370 0006c0 00 A 0 0 8
|
||||
[ 6] .ark_stackmaps PROGBITS 0000000000003a30 003a30 0010f5 00 A 0 0 8
|
||||
*/
|
||||
void ElfBuilder::PackELFSections(std::ofstream &file)
|
||||
{
|
||||
|
||||
std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
uint32_t secNum = sections.size() + 1; // 1 : section id = 0 is null section
|
||||
std::unique_ptr<llvm::ELF::Elf64_Shdr []> shdr = std::make_unique<llvm::ELF::Elf64_Shdr []>(secNum);
|
||||
if (memset_s(reinterpret_cast<void *>(&shdr[0]), sizeof(llvm::ELF::Elf64_Shdr), 0, sizeof(llvm::ELF::Elf64_Shdr)) != EOK) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
llvm::ELF::Elf64_Off curSecOffset = sizeof(llvm::ELF::Elf64_Ehdr) + secNum * sizeof(llvm::ELF::Elf64_Shdr);
|
||||
curSecOffset = AlignUp(curSecOffset, PageSize()); // not pagesize align will cause performance degradation
|
||||
file.seekp(curSecOffset);
|
||||
|
||||
int i = 1; // 1: skip null section
|
||||
auto strTab = FindStrTab();
|
||||
|
||||
for (auto &s: sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
shdr[i].sh_addralign = sectionToAlign_[s.first];
|
||||
if (curSecOffset % shdr[i].sh_addralign != 0) {
|
||||
curSecOffset = AlignUp(curSecOffset, shdr[i].sh_addralign);
|
||||
file.seekp(curSecOffset);
|
||||
}
|
||||
auto it = sectionToSegment_.find(s.first);
|
||||
ASSERT(it != sectionToSegment_.end());
|
||||
ElfSecName segName = it->second;
|
||||
segments_.insert(segName);
|
||||
uint32_t curSecSize = sectionDes_.GetSecSize(s.first);
|
||||
uint64_t curSecAddr = sectionDes_.GetSecAddr(s.first);
|
||||
std::string secName = sectionDes_.GetSecName(s.first);
|
||||
// text section address needs 16 bytes alignment
|
||||
if ((ElfSecName::RODATA <= s.first && s.first <= ElfSecName::RODATA_CST8) || s.first == ElfSecName::TEXT) {
|
||||
curSecOffset = AlignUp(curSecOffset, TEXT_SEC_ALIGN);
|
||||
file.seekp(curSecOffset);
|
||||
}
|
||||
sectionToFileOffset_[s.first] = file.tellp();
|
||||
file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
|
||||
llvm::ELF::Elf64_Word shName = FindShName(secName, strTab.first, strTab.second);
|
||||
ASSERT(shName != static_cast<llvm::ELF::Elf64_Word>(-1));
|
||||
shdr[i].sh_name = shName;
|
||||
shdr[i].sh_type = section.Type();
|
||||
shdr[i].sh_flags = section.Flag();
|
||||
shdr[i].sh_addr = curSecOffset;
|
||||
shdr[i].sh_offset = curSecOffset;
|
||||
LOG_COMPILER(DEBUG) << "curSecOffset: 0x" << std::hex << curSecOffset << " curSecSize:0x" << curSecSize;
|
||||
curSecOffset += curSecSize;
|
||||
ElfSecName lastSecName = FindLastSection(segName);
|
||||
if (s.first == lastSecName) {
|
||||
curSecOffset = AlignUp(curSecOffset, PageSize());
|
||||
file.seekp(curSecOffset);
|
||||
}
|
||||
shdr[i].sh_size = curSecSize;
|
||||
shdr[i].sh_link = section.Link();
|
||||
shdr[i].sh_info = 0;
|
||||
shdr[i].sh_entsize = section.Entsize();
|
||||
sectionToShdr_[s.first] = shdr[i];
|
||||
LOG_COMPILER(DEBUG) << " shdr[i].sh_entsize " << std::hex << shdr[i].sh_entsize << std::endl;
|
||||
++i;
|
||||
}
|
||||
uint32_t secEnd = file.tellp();
|
||||
file.seekp(sizeof(llvm::ELF::Elf64_Ehdr));
|
||||
file.write(reinterpret_cast<char *>(shdr.get()), secNum * sizeof(llvm::ELF::Elf64_Shdr));
|
||||
file.seekp(secEnd);
|
||||
}
|
||||
|
||||
unsigned ElfBuilder::GetPFlag(ElfSecName segment) const
|
||||
{
|
||||
return segmentToFlag_.at(segment);
|
||||
}
|
||||
|
||||
/*
|
||||
segment layout as follows:
|
||||
Program Headers:
|
||||
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
||||
LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x001150 0x002000 R E 0x1000
|
||||
LOAD 0x003000 0x0000000000003000 0x0000000000003000 0x001b25 0x002000 R 0x1000
|
||||
|
||||
Section to Segment mapping:
|
||||
Segment Sections...
|
||||
00 .rodata.cst8 .text
|
||||
01 .strtab .symtab .ark_funcentry .ark_stackmaps
|
||||
None
|
||||
*/
|
||||
void ElfBuilder::PackELFSegment(std::ofstream &file)
|
||||
{
|
||||
llvm::ELF::Elf64_Off e_phoff = file.tellp();
|
||||
long phoff = (long)offsetof(struct llvm::ELF::Elf64_Ehdr, e_phoff);
|
||||
// write Elf32_Off e_phoff;
|
||||
file.seekp(phoff);
|
||||
file.write(reinterpret_cast<char *>(&e_phoff), sizeof(e_phoff));
|
||||
file.seekp(e_phoff);
|
||||
|
||||
int segNum = GetSegmentNum();
|
||||
auto phdrs = std::make_unique<llvm::ELF::Elf64_Phdr []>(segNum);
|
||||
std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxOffset;
|
||||
std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxAddress;
|
||||
std::set<ElfSecName> segments;
|
||||
// SecName -> addr & size
|
||||
std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = sectionDes_.sectionsInfo_;
|
||||
llvm::ELF::Elf64_Off offset = e_phoff;
|
||||
for (auto &s: sections) {
|
||||
ElfSection section = ElfSection(s.first);
|
||||
if (!section.ShouldDumpToAOTFile()) {
|
||||
continue;
|
||||
}
|
||||
auto it = sectionToSegment_.find(s.first);
|
||||
ASSERT(it != sectionToSegment_.end());
|
||||
ElfSecName segName = it->second;
|
||||
segments.insert(segName);
|
||||
if (segmentToMaxOffset.find(segName) == segmentToMaxOffset.end()) {
|
||||
segmentToMaxOffset[segName] = 0;
|
||||
}
|
||||
segmentToMaxOffset[segName] =
|
||||
std::max(segmentToMaxOffset[segName], sectionToShdr_[s.first].sh_offset + sectionToShdr_[s.first].sh_size);
|
||||
segmentToMaxAddress[segName] =
|
||||
std::max(segmentToMaxAddress[segName], sectionToShdr_[s.first].sh_addr + sectionToShdr_[s.first].sh_size);
|
||||
offset = std::min(offset, sectionToShdr_[s.first].sh_offset);
|
||||
}
|
||||
int phdrIndex = 0;
|
||||
llvm::ELF::Elf64_Addr addr = offset;
|
||||
for (auto &it: segments) {
|
||||
ElfSecName name = it;
|
||||
phdrs[phdrIndex].p_align = PageSize();
|
||||
phdrs[phdrIndex].p_type = llvm::ELF::PT_LOAD;
|
||||
phdrs[phdrIndex].p_flags = GetPFlag(name);
|
||||
offset = AlignUp(offset, PageSize());
|
||||
phdrs[phdrIndex].p_offset = offset;
|
||||
phdrs[phdrIndex].p_vaddr = addr % phdrs[phdrIndex].p_align == 0 ?
|
||||
addr : (addr / phdrs[phdrIndex].p_align + 1) * phdrs[phdrIndex].p_align;
|
||||
phdrs[phdrIndex].p_paddr = phdrs[phdrIndex].p_vaddr;
|
||||
|
||||
phdrs[phdrIndex].p_filesz = segmentToMaxOffset[name] - phdrs[phdrIndex].p_offset;
|
||||
phdrs[phdrIndex].p_memsz = segmentToMaxAddress[name] - phdrs[phdrIndex].p_vaddr;
|
||||
phdrs[phdrIndex].p_memsz = AlignUp(phdrs[phdrIndex].p_memsz, PageSize());
|
||||
addr = phdrs[phdrIndex].p_vaddr + phdrs[phdrIndex].p_memsz;
|
||||
offset += phdrs[phdrIndex].p_filesz;
|
||||
++phdrIndex;
|
||||
}
|
||||
file.write(reinterpret_cast<char *>(phdrs.get()), sizeof(llvm::ELF::Elf64_Phdr) * segNum);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
72
ecmascript/compiler/aot_file/elf_builder.h
Normal file
72
ecmascript/compiler/aot_file/elf_builder.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_AOT_FILE_ELF_BUILDER_H
|
||||
#define ECMASCRIPT_COMPILER_AOT_FILE_ELF_BUILDER_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "ecmascript/aot_file_manager.h"
|
||||
#include "ecmascript/compiler/binary_section.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
struct ModuleSectionDes;
|
||||
|
||||
class ElfBuilder {
|
||||
public:
|
||||
ElfBuilder(ModuleSectionDes sectionDes);
|
||||
~ElfBuilder();
|
||||
void PackELFHeader(llvm::ELF::Elf64_Ehdr &header, uint32_t version, Triple triple);
|
||||
void PackELFSections(std::ofstream &elfFile);
|
||||
void PackELFSegment(std::ofstream &elfFile);
|
||||
static bool VerifyELFHeader(const llvm::ELF::Elf64_Ehdr &header, uint32_t version);
|
||||
static llvm::ELF::Elf64_Word FindShName(std::string name, uintptr_t strTabPtr, int strTabSize);
|
||||
void SetEnableSecDump(bool flag)
|
||||
{
|
||||
enableSecDump_ = flag;
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::ELF::Elf64_Half GetShStrNdx(std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions) const;
|
||||
llvm::ELF::Elf64_Half GetSecSize() const;
|
||||
ElfSecName FindLastSection(ElfSecName segment) const;
|
||||
int GetSegmentNum() const;
|
||||
int GetSecNum() const;
|
||||
unsigned GetPFlag(ElfSecName segment) const;
|
||||
std::pair<uint64_t, uint32_t> FindStrTab() const;
|
||||
bool SupportELF();
|
||||
void AddArkStackMapSection();
|
||||
void DumpSection() const;
|
||||
void ModifyStrTabSection();
|
||||
|
||||
static constexpr uint32_t TEXT_SEC_ALIGN = 16;
|
||||
ModuleSectionDes sectionDes_;
|
||||
std::unique_ptr<char []> strTabPtr_ {nullptr};
|
||||
std::map<ElfSecName, llvm::ELF::Elf64_Shdr> sectionToShdr_;
|
||||
std::map<ElfSecName, llvm::ELF::Elf64_Xword> sectionToAlign_;
|
||||
std::map<ElfSecName, ElfSecName> sectionToSegment_;
|
||||
std::map<ElfSecName, uintptr_t> sectionToFileOffset_;
|
||||
std::map<ElfSecName, unsigned> segmentToFlag_;
|
||||
std::set<ElfSecName> segments_;
|
||||
bool enableSecDump_ {false};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_COMPILER_AOT_FILE_ELF_BUILDER_H
|
||||
|
||||
|
110
ecmascript/compiler/aot_file/elf_reader.cpp
Normal file
110
ecmascript/compiler/aot_file/elf_reader.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/aot_file/elf_reader.h"
|
||||
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
bool ElfReader::VerifyELFHeader(uint32_t version)
|
||||
{
|
||||
llvm::ELF::Elf64_Ehdr header = *(reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr()));
|
||||
if (header.e_ident[llvm::ELF::EI_MAG0] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0]
|
||||
|| header.e_ident[llvm::ELF::EI_MAG1] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1]
|
||||
|| header.e_ident[llvm::ELF::EI_MAG2] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2]
|
||||
|| header.e_ident[llvm::ELF::EI_MAG3] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3]) {
|
||||
LOG_ECMA(ERROR) << "ELF format error, expected magic is " << llvm::ELF::ElfMagic
|
||||
<< ", but got " << header.e_ident[llvm::ELF::EI_MAG0] << header.e_ident[llvm::ELF::EI_MAG1]
|
||||
<< header.e_ident[llvm::ELF::EI_MAG2] << header.e_ident[llvm::ELF::EI_MAG3];
|
||||
return false;
|
||||
}
|
||||
if (header.e_version > version) {
|
||||
LOG_ECMA(ERROR) << "Elf format error, expected version should be less or equal than "
|
||||
<< version << ", but got " << header.e_version;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ElfReader::ParseELFSections(ModuleSectionDes &des, std::vector<ElfSecName> &secs)
|
||||
{
|
||||
llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr());
|
||||
char *addr = reinterpret_cast<char *>(ehdr);
|
||||
llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff);
|
||||
llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx];
|
||||
for (size_t j = 0; j < secs.size(); ++j) {
|
||||
int secId = -1;
|
||||
ElfSecName sec = secs[j];
|
||||
std::string sectionName = ModuleSectionDes::GetSecName(sec);
|
||||
for (size_t i = 0; i < ehdr->e_shnum; ++i) {
|
||||
llvm::ELF::Elf64_Word shName = shdr[i].sh_name;
|
||||
char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset;
|
||||
if (sectionName.compare(curShName) == 0) {
|
||||
secId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (secId == -1) {
|
||||
LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab";
|
||||
continue;
|
||||
}
|
||||
ASSERT(secId > 0 && secId < ehdr->e_shnum);
|
||||
llvm::ELF::Elf64_Shdr secShdr = shdr[secId];
|
||||
uintptr_t secAddr = reinterpret_cast<uintptr_t>(addr + secShdr.sh_offset);
|
||||
uint32_t secSize = secShdr.sh_size;
|
||||
if (sec == ElfSecName::ARK_FUNCENTRY) {
|
||||
ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0));
|
||||
}
|
||||
if (sec == ElfSecName::ARK_STACKMAP) {
|
||||
des.SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr));
|
||||
des.SetArkStackMapSize(secSize);
|
||||
} else {
|
||||
des.SetSecAddr(secAddr, sec);
|
||||
des.SetSecSize(secSize, sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ElfReader::ParseELFSegment()
|
||||
{
|
||||
if (fileMapMem_.GetOriginAddr() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
char *addr = reinterpret_cast<char *>(fileMapMem_.GetOriginAddr());
|
||||
llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr());
|
||||
llvm::ELF::Elf64_Phdr *phdr = reinterpret_cast<llvm::ELF::Elf64_Phdr *>(addr + ehdr->e_phoff);
|
||||
for (int i = 0; i < ehdr->e_phnum; ++i) {
|
||||
if (phdr[i].p_type != llvm::ELF::PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
if (phdr[i].p_filesz > phdr[i].p_memsz) {
|
||||
LOG_COMPILER(ERROR) << " p_filesz:0x" << std::hex << phdr[i].p_filesz << " > p_memsz:0x"
|
||||
<< phdr[i].p_memsz;
|
||||
return false;
|
||||
}
|
||||
if (!phdr[i].p_filesz) {
|
||||
continue;
|
||||
}
|
||||
unsigned char *virtualAddr = reinterpret_cast<unsigned char *>(addr + phdr[i].p_vaddr);
|
||||
ASSERT(phdr[i].p_offset % PageSize() == 0);
|
||||
if ((phdr[i].p_flags & llvm::ELF::PF_X) != 0) {
|
||||
ASSERT(reinterpret_cast<uintptr_t>(virtualAddr) % PageSize() == 0);
|
||||
PageProtect(virtualAddr, phdr[i].p_memsz, PAGE_PROT_EXEC_READ);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
40
ecmascript/compiler/aot_file/elf_reader.h
Normal file
40
ecmascript/compiler/aot_file/elf_reader.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_AOT_FILE_ELF_READER_H
|
||||
#define ECMASCRIPT_COMPILER_AOT_FILE_ELF_READER_H
|
||||
|
||||
#include <utility>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "ecmascript/aot_file_manager.h"
|
||||
#include "ecmascript/compiler/binary_section.h"
|
||||
namespace panda::ecmascript {
|
||||
|
||||
struct ModuleSectionDes;
|
||||
|
||||
class ElfReader {
|
||||
public:
|
||||
ElfReader(MemMap fileMapMem) : fileMapMem_(fileMapMem) {};
|
||||
~ElfReader() = default;
|
||||
bool VerifyELFHeader(uint32_t version);
|
||||
void ParseELFSections(ModuleSectionDes &des, std::vector<ElfSecName> &secs);
|
||||
bool ParseELFSegment();
|
||||
|
||||
private:
|
||||
MemMap fileMapMem_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_COMPILER_AOT_FILE_ELF_READER_H
|
@ -18,6 +18,12 @@
|
||||
#include "ecmascript/mem/dyn_chunk.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
enum class Triple {
|
||||
TRIPLE_AMD64,
|
||||
TRIPLE_AARCH64,
|
||||
TRIPLE_ARM32,
|
||||
};
|
||||
|
||||
class GCStackMapRegisters {
|
||||
public:
|
||||
#if defined(PANDA_TARGET_AMD64)
|
||||
|
@ -17,7 +17,9 @@
|
||||
#define ECMASCRIPT_COMPILER_BINARY_SECTION_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "ecmascript/common.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
enum class ElfSecName : uint8_t {
|
||||
@ -34,6 +36,8 @@ enum class ElfSecName : uint8_t {
|
||||
STRTAB,
|
||||
SYMTAB,
|
||||
LLVM_STACKMAP,
|
||||
ARK_FUNCENTRY,
|
||||
ARK_STACKMAP,
|
||||
SIZE
|
||||
};
|
||||
|
||||
@ -53,10 +57,12 @@ public:
|
||||
explicit ElfSection(ElfSecName idx)
|
||||
{
|
||||
value_ = idx;
|
||||
InitShTypeAndFlag();
|
||||
}
|
||||
explicit ElfSection(size_t idx)
|
||||
{
|
||||
value_ = static_cast<ElfSecName>(idx);
|
||||
InitShTypeAndFlag();
|
||||
}
|
||||
explicit ElfSection(std::string str)
|
||||
{
|
||||
@ -84,7 +90,92 @@ public:
|
||||
value_ = ElfSecName::SYMTAB;
|
||||
} else if (str.compare(".llvm_stackmaps") == 0) {
|
||||
value_ = ElfSecName::LLVM_STACKMAP;
|
||||
} else if (str.compare(".ark_stackmaps") == 0) {
|
||||
value_ = ElfSecName::ARK_STACKMAP;
|
||||
} else if (str.compare(".ark_funcentry") == 0) {
|
||||
value_ = ElfSecName::ARK_FUNCENTRY;
|
||||
}
|
||||
InitShTypeAndFlag();
|
||||
}
|
||||
|
||||
bool ShouldDumpToAOTFile() const
|
||||
{
|
||||
bool saveForAot = false;
|
||||
switch (value_) {
|
||||
case ElfSecName::RODATA:
|
||||
case ElfSecName::RODATA_CST4:
|
||||
case ElfSecName::RODATA_CST8:
|
||||
case ElfSecName::RODATA_CST16:
|
||||
case ElfSecName::RODATA_CST32:
|
||||
case ElfSecName::TEXT:
|
||||
case ElfSecName::DATA:
|
||||
case ElfSecName::SYMTAB:
|
||||
case ElfSecName::STRTAB:
|
||||
case ElfSecName::ARK_FUNCENTRY:
|
||||
case ElfSecName::ARK_STACKMAP: {
|
||||
saveForAot = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return saveForAot;
|
||||
}
|
||||
|
||||
ElfSecName Value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
int Entsize() const
|
||||
{
|
||||
if (value_ == ElfSecName::RELATEXT || value_ == ElfSecName::SYMTAB) {
|
||||
return FIX_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Link() const
|
||||
{
|
||||
return value_ == ElfSecName::SYMTAB ? 1 : 0;
|
||||
}
|
||||
|
||||
void InitShTypeAndFlag()
|
||||
{
|
||||
std::map<ElfSecName, std::pair<unsigned, unsigned>> nameToTypeAndFlag = {
|
||||
{ElfSecName::RODATA, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
|
||||
{ElfSecName::RODATA_CST4, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
|
||||
{ElfSecName::RODATA_CST8, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
|
||||
{ElfSecName::RODATA_CST16, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
|
||||
{ElfSecName::RODATA_CST32, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
|
||||
{ElfSecName::TEXT, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR)},
|
||||
{ElfSecName::DATA, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE)},
|
||||
{ElfSecName::GOT, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE)},
|
||||
{ElfSecName::RELATEXT, std::pair<unsigned, unsigned>(llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE)},
|
||||
{ElfSecName::STRTAB, std::pair<unsigned, unsigned>(llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC)},
|
||||
{ElfSecName::SYMTAB, std::pair<unsigned, unsigned>(llvm::ELF::SHT_SYMTAB, llvm::ELF::SHF_ALLOC)},
|
||||
{ElfSecName::LLVM_STACKMAP, std::pair<unsigned, unsigned>(llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC)},
|
||||
{ElfSecName::ARK_FUNCENTRY, std::pair<unsigned, unsigned>(llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC)},
|
||||
{ElfSecName::ARK_STACKMAP, std::pair<unsigned, unsigned>(llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC)},
|
||||
};
|
||||
auto it = nameToTypeAndFlag.find(value_);
|
||||
if (it == nameToTypeAndFlag.end()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(it != nameToTypeAndFlag.end());
|
||||
type_ = it->second.first;
|
||||
flag_ = it->second.second;
|
||||
}
|
||||
|
||||
unsigned Type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
unsigned Flag() const
|
||||
{
|
||||
return flag_;
|
||||
}
|
||||
|
||||
bool isValidAOTSec() const
|
||||
@ -115,7 +206,11 @@ public:
|
||||
return ElfSecName::RODATA <= value_ && value_ <= ElfSecName::RODATA_CST8;
|
||||
}
|
||||
private:
|
||||
static int const FIX_SIZE = 24; // 24:Elf_Rel
|
||||
ElfSecName value_ {ElfSecName::NONE};
|
||||
unsigned type_ {0};
|
||||
unsigned flag_ {0};
|
||||
|
||||
static constexpr size_t AOTSecFeatureTable_[static_cast<size_t>(ElfSecName::SIZE)] = {
|
||||
ElfSecFeature::NOT_VALID,
|
||||
ElfSecFeature::VALID_AND_SEQUENTIAL,
|
||||
@ -130,6 +225,7 @@ private:
|
||||
ElfSecFeature::VALID_AND_SEQUENTIAL,
|
||||
ElfSecFeature::VALID_AND_SEQUENTIAL,
|
||||
ElfSecFeature::VALID_NOT_SEQUENTIAL,
|
||||
ElfSecFeature::VALID_NOT_SEQUENTIAL,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
|
||||
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/assembler/assembler.h"
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/call_signature.h"
|
||||
@ -27,7 +28,6 @@
|
||||
#include "ecmascript/jspandafile/constpool_value.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/platform/elf.h"
|
||||
#include "ecmascript/tagged_array.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/platform/elf.h"
|
||||
|
||||
#include "ecmascript/log_wrapper.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define EI_MAG0 0
|
||||
#define ELFMAG0 0x7f
|
||||
|
||||
#define EI_MAG1 1
|
||||
#define ELFMAG1 'E'
|
||||
|
||||
#define EI_MAG2 2
|
||||
#define ELFMAG2 'L'
|
||||
|
||||
#define EI_MAG3 3
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
#define EI_CLASS 4
|
||||
#define ELFCLASS64 2
|
||||
|
||||
#define EI_DATA 5
|
||||
#define ELFDATA2LSB 1
|
||||
|
||||
#define EI_VERSION 6
|
||||
|
||||
#define ET_DYN 3
|
||||
#define EM_X86_64 62
|
||||
#define EM_ARM 40
|
||||
#define EM_AARCH64 183
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void PackELFHeader(Elf64_Ehdr &header, uint32_t version, kungfu::Triple triple)
|
||||
{
|
||||
if (memset_s(reinterpret_cast<void *>(&header), sizeof(Elf64_Ehdr), 0, sizeof(Elf64_Ehdr)) != EOK) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS64;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = 1;
|
||||
|
||||
header.e_type = ET_DYN;
|
||||
switch (triple) {
|
||||
case kungfu::Triple::TRIPLE_AMD64:
|
||||
header.e_machine = EM_X86_64;
|
||||
break;
|
||||
case kungfu::Triple::TRIPLE_ARM32:
|
||||
header.e_machine = EM_ARM;
|
||||
break;
|
||||
case kungfu::Triple::TRIPLE_AARCH64:
|
||||
header.e_machine = EM_AARCH64;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
header.e_version = version;
|
||||
}
|
||||
|
||||
bool VerifyELFHeader([[maybe_unused]] const Elf64_Ehdr &header, [[maybe_unused]] uint32_t version)
|
||||
{
|
||||
LOG_ECMA(ERROR) << "Elf is not supported on windows platform";
|
||||
return false;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_PLATFORM_ELF_H
|
||||
#define ECMASCRIPT_PLATFORM_ELF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
|
||||
#include <elf.h>
|
||||
#else
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Off;
|
||||
#define EI_NIDENT (16)
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
enum class Triple {
|
||||
TRIPLE_AMD64,
|
||||
TRIPLE_AARCH64,
|
||||
TRIPLE_ARM32,
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void PackELFHeader(Elf64_Ehdr &header, uint32_t version, kungfu::Triple triple);
|
||||
bool SupportELF();
|
||||
bool VerifyELFHeader(const Elf64_Ehdr &header, uint32_t version);
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_PLATFORM_ELF_H
|
@ -22,6 +22,7 @@
|
||||
#include <winnt.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
@ -79,6 +79,7 @@ void PUBLIC_API PageUnmap(MemMap it);
|
||||
MemMap PUBLIC_API MachineCodePageMap(size_t size, int prot = PAGE_PROT_NONE, size_t alignment = 0);
|
||||
void PUBLIC_API MachineCodePageUnmap(MemMap it);
|
||||
void PageRelease(void *mem, size_t size);
|
||||
void PagePreRead(void *mem, size_t size);
|
||||
void PageTag(void *mem, size_t size, PageTagType type);
|
||||
void PageClearTag(void *mem, size_t size);
|
||||
const char *GetPageTagString(PageTagType type);
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/platform/elf.h"
|
||||
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void PackELFHeader(Elf64_Ehdr &header, uint32_t version, kungfu::Triple triple)
|
||||
{
|
||||
if (memset_s(reinterpret_cast<void *>(&header), sizeof(Elf64_Ehdr), 0, sizeof(Elf64_Ehdr)) != EOK) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS64;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = 1;
|
||||
|
||||
header.e_type = ET_DYN;
|
||||
switch (triple) {
|
||||
case kungfu::Triple::TRIPLE_AMD64:
|
||||
header.e_machine = EM_X86_64;
|
||||
break;
|
||||
case kungfu::Triple::TRIPLE_ARM32:
|
||||
header.e_machine = EM_ARM;
|
||||
break;
|
||||
case kungfu::Triple::TRIPLE_AARCH64:
|
||||
header.e_machine = EM_AARCH64;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
header.e_version = version;
|
||||
}
|
||||
|
||||
bool VerifyELFHeader(const Elf64_Ehdr &header, uint32_t version)
|
||||
{
|
||||
if (header.e_ident[EI_MAG0] != ELFMAG0 || header.e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
header.e_ident[EI_MAG2] != ELFMAG2 || header.e_ident[EI_MAG3] != ELFMAG3) {
|
||||
LOG_ECMA(ERROR) << "ELF format error, expected magic is " << ELFMAG
|
||||
<< ", but got " << header.e_ident[EI_MAG0] << header.e_ident[EI_MAG1]
|
||||
<< header.e_ident[EI_MAG2] << header.e_ident[EI_MAG3];
|
||||
return false;
|
||||
}
|
||||
if (header.e_version > version) {
|
||||
LOG_ECMA(ERROR) << "Elf format error, expected version should be less or equal than "
|
||||
<< version << ", but got " << header.e_version;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -69,6 +69,11 @@ void PageRelease(void *mem, size_t size)
|
||||
madvise(mem, size, MADV_DONTNEED);
|
||||
}
|
||||
|
||||
void PagePreRead(void *mem, size_t size)
|
||||
{
|
||||
madvise(mem, size, MADV_WILLNEED);
|
||||
}
|
||||
|
||||
void PageTag(void *mem, size_t size, PageTagType type)
|
||||
{
|
||||
const char *tag = GetPageTagString(type);
|
||||
|
@ -83,6 +83,10 @@ void PageRelease([[maybe_unused]] void *mem, [[maybe_unused]] size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
void PagePreRead([[maybe_unused]] void *mem, [[maybe_unused]] size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
void PageTag([[maybe_unused]] void *mem, [[maybe_unused]] size_t size, [[maybe_unused]] PageTagType type)
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user