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