1 /* 2 * Copyright (c) 2023-2024 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_BASE_FILE_HEADER_H 17 #define ECMASCRIPT_BASE_FILE_HEADER_H 18 19 #include "ecmascript/base/string_helper.h" 20 #include "ecmascript/log_wrapper.h" 21 #include "utils/bit_utils.h" 22 23 #include <array> 24 #include <optional> 25 #include <stddef.h> 26 #include <stdint.h> 27 28 namespace panda::ecmascript::base { 29 class FileHeaderBase { 30 public: 31 static constexpr size_t MAGIC_SIZE = 8; 32 static constexpr size_t VERSION_SIZE = 4; 33 static constexpr uint32_t CHECKSUM_END_OFFSET = MAGIC_SIZE + VERSION_SIZE + sizeof(uint32_t); 34 static constexpr std::array<uint8_t, MAGIC_SIZE> MAGIC = {'P', 'A', 'N', 'D', 'A', '\0', '\0', '\0'}; 35 using VersionType = std::array<uint8_t, VERSION_SIZE>; 36 ToVersion(uint32_t versionNumber)37 static VersionType ToVersion(uint32_t versionNumber) 38 { 39 return bit_cast<VersionType>(ReverseBytes(versionNumber)); 40 } 41 ToVersionNumber(const VersionType & version)42 static uint32_t ToVersionNumber(const VersionType &version) 43 { 44 return ReverseBytes(bit_cast<uint32_t>(version)); 45 } 46 VerifyVersion(const char * fileDesc,uint32_t currVersion,uint32_t lastVersion,bool strictMatch)47 static bool VerifyVersion(const char *fileDesc, uint32_t currVersion, uint32_t lastVersion, bool strictMatch) 48 { 49 return VerifyVersion(fileDesc, ToVersion(currVersion), ToVersion(lastVersion), strictMatch); 50 } 51 52 template <size_t size> ConvToStr(const std::array<uint8_t,size> & array)53 static std::string ConvToStr(const std::array<uint8_t, size> &array) 54 { 55 std::string ret; 56 for (size_t i = 0; i < size; ++i) { 57 if (i) { 58 ret += "."; 59 } 60 ret += std::to_string(array.at(i)); 61 } 62 return ret; 63 } 64 strToVersion(const std::string & version)65 static std::optional<VersionType> strToVersion(const std::string& version) 66 { 67 std::vector<std::string> versionNumber = StringHelper::SplitString(version, "."); 68 VersionType formatVersion; 69 if (versionNumber.size() != VERSION_SIZE) { 70 return {}; 71 } 72 for (uint32_t i = 0; i < VERSION_SIZE; i++) { 73 uint32_t result = 0; 74 if (!StringHelper::StrToUInt32(versionNumber[i].c_str(), &result)) { 75 return {}; 76 } 77 formatVersion.at(i) = static_cast<uint8_t>(result); 78 } 79 return formatVersion; 80 } 81 VerifyVersionWithoutFile(const VersionType & currVersion,const VersionType & lastVersion)82 static bool VerifyVersionWithoutFile(const VersionType& currVersion, const VersionType& lastVersion) 83 { 84 if (currVersion > lastVersion) { 85 return true; 86 } 87 return false; 88 } 89 VerifyVersion(const char * fileDesc,const VersionType & lastVersion,bool strictMatch)90 bool VerifyVersion(const char *fileDesc, const VersionType &lastVersion, bool strictMatch) const 91 { 92 if (magic_ != MAGIC) { 93 LOG_HOST_TOOL_ERROR << "Magic mismatch, please make sure " << fileDesc 94 << " and the source code are matched"; 95 LOG_ECMA(ERROR) << "magic error, expected magic is " << ConvToStr(MAGIC) << ", but got " 96 << ConvToStr(magic_); 97 return false; 98 } 99 if (!VerifyVersion(fileDesc, version_, lastVersion, strictMatch)) { 100 return false; 101 } 102 LOG_ECMA(DEBUG) << "Magic:" << ConvToStr(magic_) << ", version:" << InternalGetVersion(); 103 return true; 104 } 105 CompatibleVerify(const VersionType & expectVersion)106 bool CompatibleVerify(const VersionType &expectVersion) const 107 { 108 return version_ >= expectVersion; 109 } 110 GetVersion()111 VersionType GetVersion() const 112 { 113 return version_; 114 } 115 SetVersion(VersionType version)116 void SetVersion(VersionType version) 117 { 118 version_ = version; 119 } 120 121 protected: FileHeaderBase(const VersionType & lastVersion)122 explicit FileHeaderBase(const VersionType &lastVersion) : magic_(MAGIC), version_(lastVersion) {} 123 VerifyVersion(const char * fileDesc,const VersionType & currVersion,const VersionType & lastVersion,bool strictMatch)124 static bool VerifyVersion(const char *fileDesc, const VersionType &currVersion, const VersionType &lastVersion, 125 bool strictMatch) 126 { 127 bool matched = strictMatch ? (currVersion == lastVersion) : (currVersion <= lastVersion); 128 if (!matched) { 129 LOG_HOST_TOOL_ERROR << fileDesc << " version error, expected version should be " 130 << (strictMatch ? "equal to " : "less or equal than ") << ConvToStr(lastVersion) 131 << ", but got " << ConvToStr(currVersion); 132 return false; 133 } 134 return true; 135 } 136 InternalGetVersion()137 std::string InternalGetVersion() const 138 { 139 return ConvToStr(version_); 140 } 141 InternalSetVersion(const std::string & version)142 bool InternalSetVersion(const std::string &version) 143 { 144 std::vector<std::string> versionNumber = StringHelper::SplitString(version, "."); 145 if (versionNumber.size() != VERSION_SIZE) { 146 LOG_ECMA(ERROR) << "version: " << version << " format error"; 147 return false; 148 } 149 for (uint32_t i = 0; i < VERSION_SIZE; i++) { 150 uint32_t result = 0; 151 if (!StringHelper::StrToUInt32(versionNumber[i].c_str(), &result)) { 152 LOG_ECMA(ERROR) << "version: " << version << " format error"; 153 return false; 154 } 155 version_.at(i) = static_cast<uint8_t>(result); 156 } 157 return true; 158 } 159 160 private: 161 std::array<uint8_t, MAGIC_SIZE> magic_; 162 VersionType version_; 163 }; 164 165 class FileHeaderElastic : public FileHeaderBase { 166 public: 167 static constexpr uint32_t ENDIAN_VALUE = 0x12345678; SetChecksum(uint32_t checksum)168 void SetChecksum(uint32_t checksum) 169 { 170 checksum_ = checksum; 171 } 172 GetChecksum()173 uint32_t GetChecksum() const 174 { 175 return checksum_; 176 } 177 SetHeaderSize(uint32_t size)178 void SetHeaderSize(uint32_t size) 179 { 180 headerSize_ = size; 181 } 182 GetHeaderSize()183 uint32_t GetHeaderSize() const 184 { 185 return headerSize_; 186 } 187 SetFileSize(uint32_t size)188 void SetFileSize(uint32_t size) 189 { 190 fileSize_ = size; 191 } 192 GetFileSize()193 uint32_t GetFileSize() const 194 { 195 return fileSize_; 196 } 197 GetEndianTag()198 uint32_t GetEndianTag() const 199 { 200 return endianTag_; 201 } 202 GetCompatibleAnVersion()203 VersionType GetCompatibleAnVersion() const 204 { 205 return compatibleAnVersion_; 206 } 207 SetCompatibleAnVersion(VersionType version)208 void SetCompatibleAnVersion(VersionType version) 209 { 210 compatibleAnVersion_ = version; 211 } 212 213 protected: FileHeaderElastic(const VersionType & lastVersion)214 explicit FileHeaderElastic(const VersionType &lastVersion) : FileHeaderBase(lastVersion) {} 215 216 private: 217 uint32_t checksum_ {0}; 218 uint32_t fileSize_ {0}; 219 uint32_t headerSize_ {0}; 220 uint32_t endianTag_ {ENDIAN_VALUE}; 221 VersionType compatibleAnVersion_; 222 }; 223 } // namespace panda::ecmascript::base 224 #endif // ECMASCRIPT_BASE_FILE_HEADER_H 225