• 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 #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