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 // The strtab index is 2 inside An file. 148 return value_ == ElfSecName::SYMTAB ? 2 : 0; 149 } 150 InitShTypeAndFlag()151 void InitShTypeAndFlag() 152 { 153 std::map<ElfSecName, std::pair<unsigned, unsigned>> nameToTypeAndFlag = { 154 {ElfSecName::RODATA, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 155 {ElfSecName::RODATA_CST4, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 156 {ElfSecName::RODATA_CST8, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 157 {ElfSecName::RODATA_CST16, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 158 {ElfSecName::RODATA_CST32, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}}, 159 {ElfSecName::TEXT, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR}}, 160 {ElfSecName::ARK_ASMSTUB, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR}}, 161 {ElfSecName::DATA, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}}, 162 {ElfSecName::GOT, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}}, 163 {ElfSecName::RELATEXT, {llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}}, 164 {ElfSecName::STRTAB, {llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC}}, 165 {ElfSecName::SYMTAB, {llvm::ELF::SHT_SYMTAB, llvm::ELF::SHF_ALLOC}}, 166 {ElfSecName::SHSTRTAB, {llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC}}, 167 {ElfSecName::LLVM_STACKMAP, {llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC}}, 168 {ElfSecName::ARK_FUNCENTRY, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}}, 169 {ElfSecName::ARK_STACKMAP, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}}, 170 {ElfSecName::ARK_MODULEINFO, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}}, 171 }; 172 auto it = nameToTypeAndFlag.find(value_); 173 if (it == nameToTypeAndFlag.end()) { 174 return; 175 } 176 ASSERT(it != nameToTypeAndFlag.end()); 177 type_ = it->second.first; 178 flag_ = it->second.second; 179 } 180 Type()181 unsigned Type() const 182 { 183 return type_; 184 } 185 Flag()186 unsigned Flag() const 187 { 188 return flag_; 189 } 190 isValidAOTSec()191 bool isValidAOTSec() const 192 { 193 auto idx = static_cast<size_t>(value_); 194 return static_cast<uint8_t>(AOTSecFeatureTable_[idx]) & ElfSecFeature::VALID_MASK; 195 } 196 isSequentialAOTSec()197 bool isSequentialAOTSec() const 198 { 199 auto idx = static_cast<size_t>(value_); 200 return static_cast<uint8_t>(AOTSecFeatureTable_[idx]) & ElfSecFeature::SEQUENTIAL_MASK; 201 } 202 GetElfEnumValue()203 ElfSecName GetElfEnumValue() const 204 { 205 return value_; 206 } 207 GetIntIndex()208 int GetIntIndex() const 209 { 210 return static_cast<int>(value_); 211 } 212 213 // RO data section needs 16 bytes alignment InRodataSection()214 bool InRodataSection() const 215 { 216 return ElfSecName::RODATA <= value_ && value_ <= ElfSecName::RODATA_CST32; 217 } 218 private: 219 static int const FIX_SIZE = 24; // 24:Elf_Rel 220 ElfSecName value_ {ElfSecName::NONE}; 221 unsigned type_ {0}; 222 unsigned flag_ {0}; 223 224 static constexpr size_t AOTSecFeatureTable_[static_cast<size_t>(ElfSecName::SIZE)] = { 225 ElfSecFeature::NOT_VALID, 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_AND_SEQUENTIAL, 238 ElfSecFeature::VALID_NOT_SEQUENTIAL, 239 ElfSecFeature::VALID_NOT_SEQUENTIAL, 240 }; 241 }; 242 } 243 #endif