• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(const std::string & fileName)17 Decompile::Decompile(const std::string &fileName) : isAlign_(false), fileName_(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 + static_cast<int32_t>(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     for (uint16_t i = 0; i < arraySize; i++) {
240         uint32_t opCode = 0;
241         if (!GetNextByteCode(opCode)) {
242             return nullptr;
243         }
244         auto element = RebuildObject(opCode);
245         if (element == nullptr) {
246             return nullptr;
247         }
248         if (!array->AddChild(element)) {
249             return nullptr;
250         }
251     }
252     return array;
253 }
254 
RebuildStringObject()255 std::shared_ptr<AstObject> Decompile::RebuildStringObject()
256 {
257     std::string strValue;
258     if (!ReadString(strValue)) {
259         return nullptr;
260     }
261     return std::make_shared<AstObject>(std::string(), PARSEROP_STRING, strValue);
262 }
263 
RebuildObject(uint8_t opCode)264 std::shared_ptr<AstObject> Decompile::RebuildObject(uint8_t opCode)
265 {
266     switch (opCode) {
267         case HCS_NODE_OP:
268             return RebuildNode();
269         case HCS_TERM_OP:
270             return RebuildTerm();
271         case HCS_NODEREF_OP:
272             return RebuildNodeRefObject();
273         case HCS_BYTE_OP:
274         case HCS_WORD_OP:
275         case HCS_DWORD_OP:
276         case HCS_QWORD_OP:
277             return RebuildNumberObject(opCode);
278         case HCS_ARRAY_OP:
279             return RebuildArray();
280         case HCS_STRING_OP:
281             return RebuildStringObject();
282         default:
283             Logger().Error() << "Rebuild object failed, unknown OpCode is: " << opCode;
284             break;
285     }
286     return nullptr;
287 }
288 
RebuildAst()289 std::shared_ptr<Ast> Decompile::RebuildAst()
290 {
291     uint32_t currByteCode = 0;
292     if (!GetNextByteCode(currByteCode) || currByteCode != HCS_NODE_OP) {
293         Logger().Error() << "Rebuild Ast failed, miss root node!";
294         return nullptr;
295     }
296     auto rootObject = RebuildObject(currByteCode);
297     if (rootObject == nullptr) {
298         Logger().Error() << "Rebuild Ast failed, rebuild object failed!";
299         return nullptr;
300     }
301     auto ast = std::make_shared<Ast>(rootObject);
302     ast->Dump();
303     return ast;
304 }
305 
DoDecompile()306 bool Decompile::DoDecompile()
307 {
308     if (!InitDecompileFile()) {
309         return false;
310     }
311 
312     if (!VerifyDecompileFile()) {
313         Logger().Error() << "Verify decompile file failed!";
314         return false;
315     }
316     auto ast = RebuildAst();
317     if (ast == nullptr) {
318         Logger().Error() << "Rebuild ast failed!";
319         return false;
320     }
321     std::string outPutFileName = Option::Instance().GetOutputName();
322     if (outPutFileName.empty()) {
323         outPutFileName = Option::Instance().GetSourceName();
324     } else if (!isalpha(outPutFileName[outPutFileName.length() - 1])) {
325         outPutFileName.append(Option::Instance().GetSourceNameBase());
326     }
327     DecompileGen decompileGen(ast, outPutFileName);
328     return decompileGen.OutPut();
329 }
330