• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 "hcs_decompiler.h"
10 #include <string.h>
11 #include "hcs_option.h"
12 #include "hcs_file.h"
13 #include "hcs_opcode.h"
14 #include "hcs_parser.h"
15 #include "hcs_log.h"
16 #include "hcs_compiler.h"
17 
18 static ParserObject *RebuildObject(uint8_t opCode);
19 
HcsVerifyHbcFile()20 static bool HcsVerifyHbcFile()
21 {
22     struct HcsFile *input = HcsSourceQueueTop();
23     HbcHeader header = { 0 };
24     uint32_t size = HcsSourceFileRead(input, (uint8_t*)&header, sizeof(header));
25     if (size != sizeof(header)) {
26         HCS_ERROR("Illegal hcb file, invalid file size");
27         return false;
28     }
29 
30     if (header.magicNumber != HBC_MAGIC_NUM) {
31         HCS_ERROR("file %s is not a hcb file", HcsGetCurrentSourceName());
32         return false;
33     }
34     if (header.totalSize < 0) {
35         HcsOptSetAlign(true);
36         header.totalSize = -header.totalSize;
37     }
38     uint32_t fileSize = HcsSourceFileGetSize(input);
39     if (fileSize != (sizeof(header) + header.totalSize)) {
40         HCS_ERROR("size mismatch, may broken file");
41         return false;
42     }
43 
44     HCS_INFO("Build by hcs compile %u.%u", header.versionMajor, header.versionMinor);
45     HCS_INFO("hcb file total size: %d\n", header.totalSize);
46     return true;
47 }
48 
49 #define HCS_STRING_READ_BUF_LEN 256
50 
ReadCString()51 static char *ReadCString()
52 {
53     char buff[HCS_STRING_READ_BUF_LEN] = {'\0'};
54     int32_t index = 0;
55     while (HcsSourceFileRead(NULL, (uint8_t*)&buff[index], sizeof(char))) {
56         if (index == HCS_STRING_READ_BUF_LEN || buff[index] == '\0') {
57             break;
58         }
59         index++;
60     }
61 
62     if (index >= HCS_STRING_READ_BUF_LEN || buff[index] != '\0') {
63         HCS_ERROR("read unterminated or too long c string at %u", HcsGetSourceFilePos(NULL));
64         return NULL;
65     }
66     uint32_t stringFullSize = index + 1;
67     uint32_t alignAppendSize = HcsAlign(stringFullSize) - stringFullSize;
68     if (alignAppendSize) {
69         uint8_t alignReadBuffer[ALIGN_SIZE];
70         if (HcsSourceFileRead(NULL, alignReadBuffer, alignAppendSize) != alignAppendSize) {
71             HCS_ERROR("read c string length mismatch %u", HcsGetSourceFilePos(NULL));
72             return NULL;
73         }
74     }
75     char *str = strdup(buff);
76     if (str == NULL) {
77         HCS_ERROR("%s:%d OOM", __func__, __LINE__);
78         return NULL;
79     }
80     return str;
81 }
82 
ReadUint64(uint64_t * value)83 static bool ReadUint64(uint64_t *value)
84 {
85     if (HcsSourceFileRead(NULL, (uint8_t*)value, sizeof(*value)) != sizeof(*value)) {
86         HCS_ERROR("fail to read uint64");
87         return false;
88     }
89     return true;
90 }
91 
ReadUint32(uint32_t * value)92 static bool ReadUint32(uint32_t *value)
93 {
94     if (HcsSourceFileRead(NULL, (uint8_t*)value, sizeof(*value)) != sizeof(*value)) {
95         HCS_ERROR("fail to read uint32");
96         return false;
97     }
98 
99     return true;
100 }
101 
ReadUint16(uint16_t * value)102 static bool ReadUint16(uint16_t *value)
103 {
104     if (HcsAlign(sizeof(uint16_t)) != sizeof(uint16_t)) {
105         uint32_t readValue = 0;
106         if (!ReadUint32(&readValue)) {
107             return false;
108         }
109         *value = (uint16_t)readValue;
110         return true;
111     }
112     if (HcsSourceFileRead(NULL, (uint8_t*)value, sizeof(*value)) != sizeof(*value)) {
113         HCS_ERROR("fail to read uint16");
114         return false;
115     }
116 
117     return true;
118 }
119 
ReadUint8(uint8_t * value)120 static bool ReadUint8(uint8_t *value)
121 {
122     if (HcsAlign(sizeof(uint8_t)) != sizeof(uint8_t)) {
123         uint32_t readValue = 0;
124         if (!ReadUint32(&readValue)) {
125             return false;
126         }
127         *value = (uint8_t)readValue;
128         return true;
129     }
130 
131     if (HcsSourceFileRead(NULL, value, sizeof(*value)) != sizeof(*value)) {
132         HCS_ERROR("fail to read uint8");
133         return false;
134     }
135 
136     return true;
137 }
138 
NextByteCode(uint32_t * byteCode)139 static bool NextByteCode(uint32_t *byteCode)
140 {
141     switch (HcsAlign(OPCODE_BYTE_WIDTH)) {
142         case BYTE_SIZE: {
143             uint8_t value = 0;
144             bool ret = ReadUint8(&value);
145             *byteCode = value;
146             return ret;
147         }
148         case DWORD_SIZE:
149             return ReadUint32(byteCode);
150         default:
151             break;
152     }
153     return false;
154 }
155 
RebuildNode()156 static ParserObject *RebuildNode()
157 {
158     uint32_t nodeHash = HcsGetSourceFilePos(NULL) - HcsAlign(OPCODE_BYTE_WIDTH);
159     char *nodeName = ReadCString();
160     if (nodeName == NULL) {
161         return NULL;
162     }
163 
164     ParserObject *node = HcsNewConfigNode(nodeName, CONFIG_NODE_NOREF, NULL);
165     if (node == NULL) {
166         HcsMemFree(nodeName);
167         return NULL;
168     }
169     uint32_t nodeSize = 0;
170     if (!ReadUint32(&nodeSize)) {
171         goto ERROR;
172     }
173     node->objectBase.hash = nodeHash;
174     node->objectBase.size = nodeSize;
175     uint32_t pos = HcsGetSourceFilePos(NULL); // node content start
176     uint64_t nodeEnd = nodeSize + pos;
177     while (pos < nodeEnd) {
178         uint32_t childOpCode;
179         if (!NextByteCode(&childOpCode)) {
180             HCS_ERROR("broken node");
181             goto ERROR;
182         }
183         ParserObject *child = RebuildObject(childOpCode);
184         if (child == NULL) {
185             goto ERROR;
186         }
187         HcsAstAddChild(node, child);
188         pos = HcsGetSourceFilePos(NULL);
189     }
190 
191     return node;
192 ERROR:
193     HcsDeleteParserObjectTree(node);
194     return NULL;
195 }
196 
RebuildTerm()197 static ParserObject *RebuildTerm()
198 {
199     char *termName = ReadCString();
200     if (termName == NULL) {
201         return NULL;
202     }
203     uint32_t childOpCode;
204     if (!NextByteCode(&childOpCode)) {
205         HCS_ERROR("broken term");
206         HcsMemFree(termName);
207         return NULL;
208     }
209 
210     ParserObject *value = RebuildObject(childOpCode);
211     if (value == NULL) {
212         HcsMemFree(termName);
213         return NULL;
214     }
215     ParserObject *term = HcsNewConfigTerm(termName, value);
216     if (term == NULL) {
217         HcsMemFree(termName);
218         HcsAstFreeObject(value);
219     }
220     return term;
221 }
222 
RebuildArray()223 static ParserObject *RebuildArray()
224 {
225     uint16_t arraySize = 0;
226     if (!ReadUint16(&arraySize)) {
227         return NULL;
228     }
229     ParserObject *array = HcsNewParserObject(NULL, PARSEROP_ARRAY, 0);
230     if (array == NULL) {
231         return NULL;
232     }
233     for (int32_t i = 0; i < arraySize; ++i) {
234         uint32_t elementOpCode;
235         if (!NextByteCode(&elementOpCode)) {
236             HCS_ERROR("broken term");
237             goto ERROR;
238         }
239         ParserObject *element = RebuildObject(elementOpCode);
240         if (element == NULL) {
241             goto ERROR;
242         }
243         HcsAstAddChild(array, element);
244     }
245     return array;
246 ERROR:
247     HcsDeleteParserObjectTree(array);
248     return NULL;
249 }
250 
RebuildNumberObject(uint8_t type)251 static ParserObject *RebuildNumberObject(uint8_t type)
252 {
253     uint8_t u8Value = 0;
254     uint16_t u16Value = 0;
255     uint32_t u32Value = 0;
256     uint64_t u64Value = 0;
257     switch (type) {
258         case HCS_BYTE_OP:
259             if (!ReadUint8(&u8Value)) {
260                 return NULL;
261             }
262             return HcsNewParserObject(NULL, PARSEROP_UINT8, u8Value);
263         case HCS_WORD_OP:
264             if (!ReadUint16(&u16Value)) {
265                 return NULL;
266             }
267             return HcsNewParserObject(NULL, PARSEROP_UINT16, u16Value);
268         case HCS_DWORD_OP:
269             if (!ReadUint32(&u32Value)) {
270                 return NULL;
271             }
272             return HcsNewParserObject(NULL, PARSEROP_UINT32, u32Value);
273         case HCS_QWORD_OP:
274             if (!ReadUint64(&u64Value)) {
275                 return NULL;
276             }
277             return HcsNewParserObject(NULL, PARSEROP_UINT64, u64Value);
278         default:
279             break;
280     }
281 
282     return NULL;
283 }
284 
RebuildStringObject()285 static ParserObject *RebuildStringObject()
286 {
287     char *objectName = ReadCString();
288     if (objectName == NULL) {
289         return NULL;
290     }
291     ParserObject *object = HcsNewParserObject(NULL, PARSEROP_STRING, (uint64_t)objectName);
292     if (object == NULL) {
293         HcsMemFree(objectName);
294     }
295     return object;
296 }
297 
RebuildNodeRefObject()298 static ParserObject *RebuildNodeRefObject()
299 {
300     uint32_t refNodeHash = 0;
301     if (!ReadUint32(&refNodeHash)) {
302         return NULL;
303     }
304 
305     return HcsNewParserObject(NULL, PARSEROP_NODEREF, refNodeHash);
306 }
307 
RebuildObject(uint8_t opCode)308 static ParserObject *RebuildObject(uint8_t opCode)
309 {
310     switch (opCode) {
311         case HCS_NODE_OP:
312             return RebuildNode();
313         case HCS_TERM_OP:
314             return RebuildTerm();
315         case HCS_NODEREF_OP:
316             return RebuildNodeRefObject();
317         case HCS_BYTE_OP: /* fall-through */
318         case HCS_WORD_OP: /* fall-through */
319         case HCS_DWORD_OP: /* fall-through */
320         case HCS_QWORD_OP:
321             return RebuildNumberObject(opCode);
322         case HCS_ARRAY_OP:
323             return RebuildArray();
324         case HCS_STRING_OP:
325             return RebuildStringObject();
326         default:
327             break;
328     }
329     HCS_ERROR("unknown OpCode %u", opCode);
330     return NULL;
331 }
332 
RebuildAst()333 static bool RebuildAst()
334 {
335     uint32_t currByteCode = 0;
336     bool ret = NextByteCode(&currByteCode);
337     if (!ret || currByteCode != HCS_NODE_OP) {
338         HCS_ERROR("miss root node");
339         return false;
340     }
341 
342     ParserObject *rootObject = RebuildObject(currByteCode);
343     if (rootObject == NULL) {
344         return false;
345     }
346 
347     HcsSetParserRoot(rootObject);
348     return true;
349 }
350 
HcsDoDecompile(void)351 int32_t HcsDoDecompile(void)
352 {
353     struct HcsFile *source = NULL;
354     uint32_t ret = HcsOpenSourceFile(HcsGetInputFileName(), &source, "rb");
355     if (ret) {
356         return ret;
357     }
358     HcsSourceQueuePush(source);
359 
360     do {
361         if (!HcsVerifyHbcFile()) {
362             ret = EDECOMP;
363             break;
364         }
365 
366         if (!RebuildAst()) {
367             HCS_ERROR("failed to rebuild ast from hcb file");
368             ret = EDECOMP;
369             break;
370         }
371         if (HcsVerbosePrint()) {
372             HcsDumpAst("Rebuild");
373         }
374     } while (0);
375 
376     HcsSourceQueuePop();
377     HcsCloseFile(source);
378     if (ret == NOERR) {
379         ret = HcsDecompileOutput();
380     }
381     HcsDeleteParserObjectTree(HcsGetParserRoot());
382     HcsSetParserRoot(NULL);
383     HcsSourceNameSetClean();
384     return ret;
385 }