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