1 /* 2 * Copyright (c) 2021-2022 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 #ifndef ECMASCRIPT_COMPILER_BINARY_SECTION_H 17 #define ECMASCRIPT_COMPILER_BINARY_SECTION_H 18 19 #include <string> 20 #include <map> 21 #include "ecmascript/common.h" 22 #include "llvm/BinaryFormat/ELF.h" 23 24 namespace panda::ecmascript { 25 enum class ElfSecName : uint8_t { 26 NONE, 27 RODATA, 28 RODATA_CST4, 29 RODATA_CST8, 30 RODATA_CST16, 31 RODATA_CST32, 32 TEXT, 33 ARK_ASMSTUB, 34 DATA, 35 GOT, 36 RELATEXT, 37 STRTAB, 38 SYMTAB, 39 SHSTRTAB, 40 LLVM_STACKMAP, 41 ARK_FUNCENTRY, 42 ARK_STACKMAP, 43 ARK_MODULEINFO, 44 SIZE 45 }; 46 47 enum ElfSecFeature : uint8_t { 48 NOT_VALID, 49 VALID_NOT_SEQUENTIAL = 1, 50 VALID_AND_SEQUENTIAL = (1 << 1) | 1, 51 52 VALID_MASK = 0x1, 53 SEQUENTIAL_MASK = 0x2 54 }; 55 56 class PUBLIC_API ElfSection { 57 public: 58 ElfSection() = delete; 59 ElfSection(ElfSecName idx)60 explicit ElfSection(ElfSecName idx) 61 { 62 value_ = idx; 63 InitShTypeAndFlag(); 64 } ElfSection(size_t idx)65 explicit ElfSection(size_t idx) 66 { 67 value_ = static_cast<ElfSecName>(idx); 68 InitShTypeAndFlag(); 69 } ElfSection(std::string str)70 explicit ElfSection(std::string str) 71 { 72 if (str.compare(".rodata") == 0) { 73 value_ = ElfSecName::RODATA; 74 } else if (str.compare(".rodata.cst4") == 0) { 75 value_ = ElfSecName::RODATA_CST4; 76 } else if (str.compare(".rodata.cst8") == 0) { 77 value_ = ElfSecName::RODATA_CST8; 78 } else if (str.compare(".rodata.cst16") == 0) { 79 value_ = ElfSecName::RODATA_CST16; 80 } else if (str.compare(".rodata.cst32") == 0) { 81 value_ = ElfSecName::RODATA_CST32; 82 } else if (str.compare(".text") == 0) { 83 value_ = ElfSecName::TEXT; 84 } else if (str.compare(".data") == 0) { 85 value_ = ElfSecName::DATA; 86 } else if (str.compare(".got") == 0) { 87 value_ = ElfSecName::GOT; 88 } else if (str.compare(".rela.text") == 0) { 89 value_ = ElfSecName::RELATEXT; 90 } else if (str.compare(".strtab") == 0) { 91 value_ = ElfSecName::STRTAB; 92 } else if (str.compare(".symtab") == 0) { 93 value_ = ElfSecName::SYMTAB; 94 } else if (str.compare(".shstrtab") == 0) { 95 value_ = ElfSecName::SHSTRTAB; 96 } else if (str.compare(".llvm_stackmaps") == 0) { 97 value_ = ElfSecName::LLVM_STACKMAP; 98 } else if (str.compare(".ark_stackmaps") == 0) { 99 value_ = ElfSecName::ARK_STACKMAP; 100 } else if (str.compare(".ark_funcentry") == 0) { 101 value_ = ElfSecName::ARK_FUNCENTRY; 102 } else if (str.compare(".ark_asmstub") == 0) { 103 value_ = ElfSecName::ARK_ASMSTUB; 104 } else if (str.compare(".ark_moduleinfo") == 0) { 105 value_ = ElfSecName::ARK_MODULEINFO; 106 } 107 InitShTypeAndFlag(); 108 } 109 ShouldDumpToAOTFile()110 bool ShouldDumpToAOTFile() const 111 { 112 bool saveForAot = false; 113 switch (value_) { 114 case ElfSecName::TEXT: 115 case ElfSecName::STRTAB: 116 case ElfSecName::SYMTAB: 117 case ElfSecName::SHSTRTAB: 118 case ElfSecName::ARK_FUNCENTRY: 119 case ElfSecName::ARK_ASMSTUB: 120 case ElfSecName::ARK_STACKMAP: 121 case ElfSecName::ARK_MODULEINFO: { 122 saveForAot = true; 123 break; 124 } 125 default: { 126 break; 127 } 128 } 129 return saveForAot; 130 } 131 Value()132 ElfSecName Value() const 133 { 134 return value_; 135 } 136 Entsize()137 int Entsize() const 138 { 139 if (value_ == ElfSecName::RELATEXT || value_ == ElfSecName::SYMTAB) { 140 return FIX_SIZE; 141 } 142 return 0; 143 } 144 Link()145 int Link() const 146 { 147 return value_ == ElfSecName::SYMTAB ? 1 : 0; 148 } 149 InitShTypeAndFlag()150 void InitShTypeAndFlag() 151 { 152 std::map<ElfSecName, std::pair<unsigned, unsigned>> nameToTypeAndFlag = { 153 {ElfSecName::RODATA, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 154 {ElfSecName::RODATA_CST4, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 155 {ElfSecName::RODATA_CST8, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 156 {ElfSecName::RODATA_CST16, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 157 {ElfSecName::RODATA_CST32, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 158 {ElfSecName::TEXT, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR}}, 159 {ElfSecName::ARK_ASMSTUB, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR}}, 160 {ElfSecName::DATA, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}}, 161 {ElfSecName::GOT, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}}, 162 {ElfSecName::RELATEXT, {llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}}, 163 {ElfSecName::STRTAB, {llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC}}, 164 {ElfSecName::SYMTAB, {llvm::ELF::SHT_SYMTAB, llvm::ELF::SHF_ALLOC}}, 165 {ElfSecName::SHSTRTAB, {llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC}}, 166 {ElfSecName::LLVM_STACKMAP, {llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC}}, 167 {ElfSecName::ARK_FUNCENTRY, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}}, 168 {ElfSecName::ARK_STACKMAP, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}}, 169 {ElfSecName::ARK_MODULEINFO, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}}, 170 }; 171 auto it = nameToTypeAndFlag.find(value_); 172 if (it == nameToTypeAndFlag.end()) { 173 return; 174 } 175 ASSERT(it != nameToTypeAndFlag.end()); 176 type_ = it->second.first; 177 flag_ = it->second.second; 178 } 179 Type()180 unsigned Type() const 181 { 182 return type_; 183 } 184 Flag()185 unsigned Flag() const 186 { 187 return flag_; 188 } 189 isValidAOTSec()190 bool isValidAOTSec() const 191 { 192 auto idx = static_cast<size_t>(value_); 193 return static_cast<uint8_t>(AOTSecFeatureTable_[idx]) & ElfSecFeature::VALID_MASK; 194 } 195 isSequentialAOTSec()196 bool isSequentialAOTSec() const 197 { 198 auto idx = static_cast<size_t>(value_); 199 return static_cast<uint8_t>(AOTSecFeatureTable_[idx]) & ElfSecFeature::SEQUENTIAL_MASK; 200 } 201 GetElfEnumValue()202 ElfSecName GetElfEnumValue() const 203 { 204 return value_; 205 } 206 GetIntIndex()207 int GetIntIndex() const 208 { 209 return static_cast<int>(value_); 210 } 211 212 // RO data section needs 16 bytes alignment InRodataSection()213 bool InRodataSection() const 214 { 215 return ElfSecName::RODATA <= value_ && value_ <= ElfSecName::RODATA_CST32; 216 } 217 private: 218 static int const FIX_SIZE = 24; // 24:Elf_Rel 219 ElfSecName value_ {ElfSecName::NONE}; 220 unsigned type_ {0}; 221 unsigned flag_ {0}; 222 223 static constexpr size_t AOTSecFeatureTable_[static_cast<size_t>(ElfSecName::SIZE)] = { 224 ElfSecFeature::NOT_VALID, 225 ElfSecFeature::VALID_AND_SEQUENTIAL, 226 ElfSecFeature::VALID_AND_SEQUENTIAL, 227 ElfSecFeature::VALID_AND_SEQUENTIAL, 228 ElfSecFeature::VALID_AND_SEQUENTIAL, 229 ElfSecFeature::VALID_AND_SEQUENTIAL, 230 ElfSecFeature::VALID_AND_SEQUENTIAL, 231 ElfSecFeature::VALID_AND_SEQUENTIAL, 232 ElfSecFeature::VALID_AND_SEQUENTIAL, 233 ElfSecFeature::VALID_AND_SEQUENTIAL, 234 ElfSecFeature::VALID_AND_SEQUENTIAL, 235 ElfSecFeature::VALID_AND_SEQUENTIAL, 236 ElfSecFeature::VALID_AND_SEQUENTIAL, 237 ElfSecFeature::VALID_NOT_SEQUENTIAL, 238 ElfSecFeature::VALID_NOT_SEQUENTIAL, 239 }; 240 }; 241 } 242 #endif