• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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