1 /* 2 * Copyright (c) 2023 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 <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 VerifyVersion(const char * fileDesc,const VersionType & lastVersion,bool strictMatch)65 bool VerifyVersion(const char *fileDesc, const VersionType &lastVersion, bool strictMatch) const 66 { 67 if (magic_ != MAGIC) { 68 LOG_HOST_TOOL_ERROR << "Magic mismatch, please make sure " << fileDesc 69 << " and the source code are matched"; 70 LOG_ECMA(ERROR) << "magic error, expected magic is " << ConvToStr(MAGIC) << ", but got " 71 << ConvToStr(magic_); 72 return false; 73 } 74 if (!VerifyVersion(fileDesc, version_, lastVersion, strictMatch)) { 75 return false; 76 } 77 LOG_ECMA(DEBUG) << "Magic:" << ConvToStr(magic_) << ", version:" << InternalGetVersion(); 78 return true; 79 } 80 CompatibleVerify(const VersionType & expectVersion)81 bool CompatibleVerify(const VersionType &expectVersion) const 82 { 83 return version_ >= expectVersion; 84 } 85 GetVersion()86 VersionType GetVersion() const 87 { 88 return version_; 89 } 90 SetVersion(VersionType version)91 void SetVersion(VersionType version) 92 { 93 version_ = version; 94 } 95 96 protected: FileHeaderBase(const VersionType & lastVersion)97 explicit FileHeaderBase(const VersionType &lastVersion) : magic_(MAGIC), version_(lastVersion) {} 98 VerifyVersion(const char * fileDesc,const VersionType & currVersion,const VersionType & lastVersion,bool strictMatch)99 static bool VerifyVersion(const char *fileDesc, const VersionType &currVersion, const VersionType &lastVersion, 100 bool strictMatch) 101 { 102 bool matched = strictMatch ? (currVersion == lastVersion) : (currVersion <= lastVersion); 103 if (!matched) { 104 LOG_HOST_TOOL_ERROR << fileDesc << " version error, expected version should be " 105 << (strictMatch ? "equal to " : "less or equal than ") << ConvToStr(lastVersion) 106 << ", but got " << ConvToStr(currVersion); 107 return false; 108 } 109 return true; 110 } 111 InternalGetVersion()112 std::string InternalGetVersion() const 113 { 114 return ConvToStr(version_); 115 } 116 InternalSetVersion(const std::string & version)117 bool InternalSetVersion(const std::string &version) 118 { 119 std::vector<std::string> versionNumber = StringHelper::SplitString(version, "."); 120 if (versionNumber.size() != VERSION_SIZE) { 121 LOG_ECMA(ERROR) << "version: " << version << " format error"; 122 return false; 123 } 124 for (uint32_t i = 0; i < VERSION_SIZE; i++) { 125 uint32_t result = 0; 126 if (!StringHelper::StrToUInt32(versionNumber[i].c_str(), &result)) { 127 LOG_ECMA(ERROR) << "version: " << version << " format error"; 128 return false; 129 } 130 version_.at(i) = static_cast<uint8_t>(result); 131 } 132 return true; 133 } 134 135 private: 136 std::array<uint8_t, MAGIC_SIZE> magic_; 137 VersionType version_; 138 }; 139 140 class FileHeaderElastic : public FileHeaderBase { 141 public: 142 static constexpr uint32_t ENDIAN_VALUE = 0x12345678; SetChecksum(uint32_t checksum)143 void SetChecksum(uint32_t checksum) 144 { 145 checksum_ = checksum; 146 } 147 GetChecksum()148 uint32_t GetChecksum() const 149 { 150 return checksum_; 151 } 152 SetHeaderSize(uint32_t size)153 void SetHeaderSize(uint32_t size) 154 { 155 headerSize_ = size; 156 } 157 GetHeaderSize()158 uint32_t GetHeaderSize() const 159 { 160 return headerSize_; 161 } 162 SetFileSize(uint32_t size)163 void SetFileSize(uint32_t size) 164 { 165 fileSize_ = size; 166 } 167 GetFileSize()168 uint32_t GetFileSize() const 169 { 170 return fileSize_; 171 } 172 GetEndianTag()173 uint32_t GetEndianTag() const 174 { 175 return endianTag_; 176 } 177 178 protected: FileHeaderElastic(const VersionType & lastVersion)179 explicit FileHeaderElastic(const VersionType &lastVersion) : FileHeaderBase(lastVersion) {} 180 181 private: 182 uint32_t checksum_ {0}; 183 uint32_t fileSize_ {0}; 184 uint32_t headerSize_ {0}; 185 uint32_t endianTag_ {ENDIAN_VALUE}; 186 }; 187 } // namespace panda::ecmascript::base 188 #endif // ECMASCRIPT_BASE_FILE_HEADER_H 189