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