1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "decompile.h"
10 #include <cctype>
11 #include "decompile_gen.h"
12 #include "logger.h"
13 #include "opcode.h"
14
15 using namespace OHOS::Hardware;
16
Decompile(std::string fileName)17 Decompile::Decompile(std::string fileName) : isAlign_(false), fileName_(std::move(fileName)) {}
18
InitDecompileFile()19 bool Decompile::InitDecompileFile()
20 {
21 file_.open(fileName_.data(), std::ios::binary);
22 if (!file_.is_open()) {
23 Logger().Error() << "Failed to open decompile file: " << fileName_;
24 return false;
25 }
26 return true;
27 }
28
ReadFile(char * buffer,size_t readSize)29 bool Decompile::ReadFile(char *buffer, size_t readSize)
30 {
31 if (!file_.read(buffer, static_cast<std::streamsize>(readSize))) {
32 Logger().Error() << "read file failed, read size is: " << readSize;
33 return false;
34 }
35 return true;
36 }
37
SetAlign(bool isAlign)38 void Decompile::SetAlign(bool isAlign)
39 {
40 isAlign_ = isAlign;
41 }
42
VerifyDecompileFile()43 bool Decompile::VerifyDecompileFile()
44 {
45 HcbHeader header {0};
46 if (!ReadFile(reinterpret_cast<char *>(&header), sizeof(header))) {
47 Logger().Error() << "read header failed";
48 return false;
49 }
50 Logger().Debug() << "read Header: magic is: " << header.magicNumber << " version major: " << header.versionMajor
51 << " version minor: " << header.versionMinor << " checksum: " << header.checkSum
52 << " totalSize: " << header.totalSize;
53 if (header.magicNumber != HCB_MAGIC_NUM) {
54 Logger().Error() << "magic number is: " << header.magicNumber << ", check failed!";
55 return false;
56 }
57 if (header.totalSize < 0) {
58 SetAlign(true);
59 header.totalSize = -header.totalSize;
60 }
61 return true;
62 }
63
ReadUint32(uint32_t & value)64 bool Decompile::ReadUint32(uint32_t &value)
65 {
66 return ReadFile(reinterpret_cast<char *>(&value), sizeof(uint32_t));
67 }
68
ReadUint8(uint8_t & value)69 bool Decompile::ReadUint8(uint8_t &value)
70 {
71 if (GetAlignSize(sizeof(uint8_t)) != sizeof(uint8_t)) {
72 uint32_t readValue = 0;
73 if (!ReadUint32(readValue)) {
74 return false;
75 }
76 value = static_cast<uint8_t>(readValue);
77 return true;
78 }
79 return ReadFile(reinterpret_cast<char *>(&value), sizeof(uint8_t));
80 }
81
ReadUint16(uint16_t & value)82 bool Decompile::ReadUint16(uint16_t &value)
83 {
84 if (GetAlignSize(sizeof(uint16_t)) != sizeof(uint16_t)) {
85 uint32_t readValue = 0;
86 if (!ReadUint32(readValue)) {
87 return false;
88 }
89 value = static_cast<uint16_t>(readValue);
90 return true;
91 }
92 return ReadFile(reinterpret_cast<char *>(&value), sizeof(uint16_t));
93 }
94
ReadUint64(uint64_t & value)95 bool Decompile::ReadUint64(uint64_t &value)
96 {
97 return ReadFile(reinterpret_cast<char *>(&value), sizeof(uint64_t));
98 }
99
ReadString(std::string & value)100 bool Decompile::ReadString(std::string &value)
101 {
102 value.clear();
103 char c;
104 while (ReadFile(&c, sizeof(c))) {
105 if (c == '\0') {
106 break;
107 }
108 if (value.length() > NUMBER) {
109 return false;
110 }
111 value += c;
112 }
113 uint32_t alignSize = GetAlignSize(value.length() + 1) - (value.length() + 1);
114 if (alignSize > 0) {
115 char alignReadBuff[4];
116 if (!ReadFile(alignReadBuff, alignSize)) {
117 return false;
118 }
119 }
120 return true;
121 }
122
GetNextByteCode(uint32_t & byteCode)123 bool Decompile::GetNextByteCode(uint32_t &byteCode)
124 {
125 if (GetAlignSize(OPCODE_BYTE_WIDTH) == OPCODE_BYTE_WIDTH) {
126 uint8_t value = 0;
127 bool ret = ReadUint8(value);
128 byteCode = value;
129 return ret;
130 } else {
131 return ReadUint32(byteCode);
132 }
133 }
134
RebuildNode()135 std::shared_ptr<AstObject> Decompile::RebuildNode()
136 {
137 uint32_t nodeHash = static_cast<uint32_t>(file_.tellg()) - GetAlignSize(OPCODE_BYTE_WIDTH);
138 std::string nodeName;
139 if (!ReadString(nodeName)) {
140 return nullptr;
141 }
142
143 auto node = std::make_shared<ConfigNode>(nodeName, NODE_NOREF, "");
144 uint32_t nodeSize = 0;
145 if (!ReadUint32(nodeSize)) {
146 return nullptr;
147 }
148 node->SetSize(nodeSize);
149 node->SetHash(nodeHash);
150 Logger().Debug() << "node name is: " << node->Name() << ", size is: " << nodeSize << ", hash is: " << nodeHash;
151 int32_t pos = file_.tellg();
152 int32_t nodeEnd = pos + nodeSize;
153 while (pos < nodeEnd) {
154 uint32_t childOpCode;
155 if (!GetNextByteCode(childOpCode)) {
156 Logger().Error() << "Rebuild node failed, get next byte code failed";
157 return nullptr;
158 }
159 auto child = RebuildObject(childOpCode);
160 if (child == nullptr) {
161 Logger().Error() << "Rebuild node failed, get child failed";
162 return nullptr;
163 }
164 if (!node->AddChild(child)) {
165 Logger().Error() << "Rebuild node failed, add child failed";
166 return nullptr;
167 }
168 pos = file_.tellg();
169 }
170 return node;
171 }
172
RebuildTerm()173 std::shared_ptr<AstObject> Decompile::RebuildTerm()
174 {
175 std::string termName;
176 if (!ReadString(termName)) {
177 return nullptr;
178 }
179 uint32_t childOpCode;
180 if (!GetNextByteCode(childOpCode)) {
181 return nullptr;
182 }
183 auto value = RebuildObject(childOpCode);
184 if (value == nullptr) {
185 return nullptr;
186 }
187 return std::make_shared<ConfigTerm>(termName, value);
188 }
189
RebuildNodeRefObject()190 std::shared_ptr<AstObject> Decompile::RebuildNodeRefObject()
191 {
192 uint32_t refNodeHash = 0;
193 if (!ReadUint32(refNodeHash)) {
194 return nullptr;
195 }
196 Logger().Debug() << "Ref object value is: " << refNodeHash;
197 return std::make_shared<AstObject>(std::string(), PARSEROP_NODEREF, refNodeHash);
198 }
199
RebuildNumberObject(uint8_t opCode)200 std::shared_ptr<AstObject> Decompile::RebuildNumberObject(uint8_t opCode)
201 {
202 uint8_t u8Value = 0;
203 uint16_t u16Value = 0;
204 uint32_t u32Value = 0;
205 uint64_t u64Value = 0;
206 switch (opCode) {
207 case HCS_BYTE_OP:
208 if (!ReadUint8(u8Value)) {
209 return nullptr;
210 }
211 return std::make_shared<AstObject>(std::string(), PARSEROP_UINT8, u8Value);
212 case HCS_WORD_OP:
213 if (!ReadUint16(u16Value)) {
214 return nullptr;
215 }
216 return std::make_shared<AstObject>(std::string(), PARSEROP_UINT16, u16Value);
217 case HCS_DWORD_OP:
218 if (!ReadUint32(u32Value)) {
219 return nullptr;
220 }
221 return std::make_shared<AstObject>(std::string(), PARSEROP_UINT32, u32Value);
222 case HCS_QWORD_OP:
223 if (!ReadUint64(u64Value)) {
224 return nullptr;
225 }
226 return std::make_shared<AstObject>(std::string(), PARSEROP_UINT64, u64Value);
227 default:
228 return nullptr;
229 }
230 }
231
RebuildArray()232 std::shared_ptr<AstObject> Decompile::RebuildArray()
233 {
234 uint16_t arraySize = 0;
235 if (!ReadUint16(arraySize)) {
236 return nullptr;
237 }
238 auto array = std::make_shared<AstObject>(std::string(), PARSEROP_ARRAY, 0);
239 if (array == nullptr) {
240 return nullptr;
241 }
242 for (uint16_t i = 0; i < arraySize; i++) {
243 uint32_t opCode = 0;
244 if (!GetNextByteCode(opCode)) {
245 return nullptr;
246 }
247 auto element = RebuildObject(opCode);
248 if (element == nullptr) {
249 return nullptr;
250 }
251 if (!array->AddChild(element)) {
252 return nullptr;
253 }
254 }
255 return array;
256 }
257
RebuildStringObject()258 std::shared_ptr<AstObject> Decompile::RebuildStringObject()
259 {
260 std::string strValue;
261 if (!ReadString(strValue)) {
262 return nullptr;
263 }
264 return std::make_shared<AstObject>(std::string(), PARSEROP_STRING, strValue);
265 }
266
RebuildObject(uint8_t opCode)267 std::shared_ptr<AstObject> Decompile::RebuildObject(uint8_t opCode)
268 {
269 switch (opCode) {
270 case HCS_NODE_OP:
271 return RebuildNode();
272 case HCS_TERM_OP:
273 return RebuildTerm();
274 case HCS_NODEREF_OP:
275 return RebuildNodeRefObject();
276 case HCS_BYTE_OP:
277 case HCS_WORD_OP:
278 case HCS_DWORD_OP:
279 case HCS_QWORD_OP:
280 return RebuildNumberObject(opCode);
281 case HCS_ARRAY_OP:
282 return RebuildArray();
283 case HCS_STRING_OP:
284 return RebuildStringObject();
285 default:
286 Logger().Error() << "Rebuild object failed, unknown OpCode is: " << opCode;
287 break;
288 }
289 return nullptr;
290 }
291
RebuildAst()292 std::shared_ptr<Ast> Decompile::RebuildAst()
293 {
294 uint32_t currByteCode = 0;
295 if (!GetNextByteCode(currByteCode) || currByteCode != HCS_NODE_OP) {
296 Logger().Error() << "Rebuild Ast failed, miss root node!";
297 return nullptr;
298 }
299 auto rootObject = RebuildObject(currByteCode);
300 if (rootObject == nullptr) {
301 Logger().Error() << "Rebuild Ast failed, rebuild object failed!";
302 return nullptr;
303 }
304 auto ast = std::make_shared<Ast>(rootObject);
305 ast->Dump();
306 return ast;
307 }
308
DoDecompile()309 bool Decompile::DoDecompile()
310 {
311 if (!InitDecompileFile()) {
312 return false;
313 }
314
315 if (!VerifyDecompileFile()) {
316 Logger().Error() << "Verify decompile file failed!";
317 return false;
318 }
319 auto ast = RebuildAst();
320 if (ast == nullptr) {
321 Logger().Error() << "Rebuild ast failed!";
322 return false;
323 }
324 std::string outPutFileName = Option::Instance().GetOutputName();
325 if (outPutFileName.empty()) {
326 outPutFileName = Option::Instance().GetSourceName();
327 } else if (!isalpha(outPutFileName[outPutFileName.length() - 1])) {
328 outPutFileName.append(Option::Instance().GetSourceNameBase());
329 }
330 DecompileGen decompileGen(ast, outPutFileName);
331 return decompileGen.OutPut();
332 }
333