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