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