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 <string.h>
10 #include <securec.h>
11 #include "hcs_file.h"
12 #include "hcs_ast.h"
13 #include "hcs_mem.h"
14 #include "hcs_log.h"
15
16 #define WRITE_BUFFER_LEN 256
17 #define HCS_TAB_SIZE 4
18
19 #define HCS_DECOMPILE_FILE_HEADER \
20 "/*\n" \
21 " * HDF decompile hcs file\n" \
22 " */\n\n"
23
HcsAssembleNodeRefName(char * buff,uint32_t buffSize,const char * name)24 static char *HcsAssembleNodeRefName(char *buff, uint32_t buffSize, const char *name)
25 {
26 int32_t res = strcat_s(buff, buffSize, name);
27 if (res) {
28 HCS_ERROR("%s:%d: string cat fail", __func__, __LINE__);
29 return NULL;
30 }
31 char *str = strdup(buff);
32 if (str == NULL) {
33 HCS_ERROR("%s:%d OOM", __func__, __LINE__);
34 return NULL;
35 }
36 return str;
37 }
38
HcsGetNodeRefPath(uint64_t hash)39 static char *HcsGetNodeRefPath(uint64_t hash)
40 {
41 char pathBuffer[WRITE_BUFFER_LEN] = {'\0'};
42 char *path = pathBuffer;
43 ParserObjectBase *it = (ParserObjectBase *)HcsGetParserRoot();
44 if (it == NULL) {
45 return NULL;
46 }
47
48 while (it->child) {
49 int32_t res = strcat_s(path, WRITE_BUFFER_LEN, it->name);
50 if (res) {
51 HCS_ERROR("%s:%d: strcat fail", __func__, __LINE__);
52 return NULL;
53 }
54 res = strcat_s(path, WRITE_BUFFER_LEN, ".");
55 if (res) {
56 HCS_ERROR("%s:%d: strcat fail", __func__, __LINE__);
57 return NULL;
58 }
59 ParserObjectBase *child = it->child;
60 bool deepIn = false;
61 while (child != NULL) {
62 if (child->type != PARSEROP_CONFNODE) {
63 child = child->next;
64 continue;
65 }
66 if (child->hash == hash) {
67 return HcsAssembleNodeRefName(pathBuffer, WRITE_BUFFER_LEN, child->name);
68 }
69
70 if (hash > child->hash && hash < (child->hash + child->size)) {
71 it = child;
72 deepIn = true;
73 break;
74 }
75 child = child->next;
76 }
77 if (!deepIn) {
78 HCS_ERROR("ref unknown node, hash = %"PRIu64, hash);
79 return NULL;
80 }
81 }
82
83 return NULL;
84 }
85
86 static int32_t HcsDecompilePrintBaseType(const ParserObject *object);
87
HcsDecompilePrintArrayType(const ParserObject * object)88 static int32_t HcsDecompilePrintArrayType(const ParserObject *object)
89 {
90 int32_t res;
91 PRINTF_CHECK_AND_RETURN(HcsFormatOutputWrite("["));
92 ParserObject *arrayElement = (ParserObject *)object->objectBase.child;
93 while (arrayElement->objectBase.next) {
94 res = HcsDecompilePrintBaseType(arrayElement);
95 if (res) {
96 return EOUTPUT;
97 }
98 PRINTF_CHECK_AND_RETURN(HcsFormatOutputWrite(", "));
99 arrayElement = (ParserObject *)arrayElement->objectBase.next;
100 }
101 res = HcsDecompilePrintBaseType(arrayElement);
102 if (res) {
103 return EOUTPUT;
104 }
105
106 return HcsFormatOutputWrite("]");
107 }
108
HcsDecompilePrintBaseType(const ParserObject * object)109 static int32_t HcsDecompilePrintBaseType(const ParserObject *object)
110 {
111 int32_t res = NOERR;
112 switch (object->objectBase.type) {
113 case PARSEROP_UINT8:
114 case PARSEROP_UINT16:
115 case PARSEROP_UINT32:
116 case PARSEROP_UINT64:
117 res = HcsFormatOutputWrite("0x%"PRIx64, object->objectBase.integerValue);
118 break;
119 case PARSEROP_STRING:
120 res = HcsFormatOutputWrite("\"%s\"", object->objectBase.stringValue);
121 break;
122 case PARSEROP_NODEREF: {
123 char *refPath = HcsGetNodeRefPath(object->objectBase.value);
124 if (refPath == NULL) {
125 return EOUTPUT;
126 }
127 res = HcsFormatOutputWrite("&%s", refPath);
128 HcsMemFree(refPath);
129 }
130 break;
131 case PARSEROP_ARRAY:
132 return HcsDecompilePrintArrayType(object);
133 default:
134 HCS_ERROR("unknown OpCode %u", object->objectBase.type);
135 return EFAIL;
136 }
137
138 return res;
139 }
140
HcsDecompileOutputWalk(ParserObject * current,int32_t walkDepth)141 static int32_t HcsDecompileOutputWalk(ParserObject *current, int32_t walkDepth)
142 {
143 if (current->objectBase.type != PARSEROP_CONFNODE && current->objectBase.type != PARSEROP_CONFTERM) {
144 return NOERR;
145 }
146
147 int32_t res;
148 int32_t tabSize = walkDepth * HCS_TAB_SIZE;
149 if (walkDepth) {
150 PRINTF_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", tabSize, ' '));
151 }
152
153 switch (current->objectBase.type) {
154 case PARSEROP_CONFNODE:
155 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s {\n", current->configNode.name));
156 if (current->objectBase.child == NULL) {
157 return HcsFormatOutputWrite("%*c}\n", tabSize, ' ');
158 }
159 break;
160 case PARSEROP_CONFTERM:
161 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s = ", current->configNode.name));
162 res = HcsDecompilePrintBaseType(
163 (ParserObject *) current->configNode.child);
164 if (res) {
165 return res;
166 }
167 return HcsFormatOutputWrite(";\n");
168 default:
169 break;
170 }
171
172 return NOERR;
173 }
174
HcsDecompileCloseBraceGen(ParserObject * current,int32_t walkDepth)175 static int32_t HcsDecompileCloseBraceGen(ParserObject *current, int32_t walkDepth)
176 {
177 if (current->objectBase.type != PARSEROP_CONFNODE) {
178 return NOERR;
179 }
180 int32_t tabSize = walkDepth * HCS_TAB_SIZE;
181
182 return current != HcsGetParserRoot() ? HcsFormatOutputWrite("%*c}\n", tabSize, ' ') :
183 HcsFormatOutputWrite("}\n");
184 }
185
HcsDecompileOutput(void)186 int32_t HcsDecompileOutput(void)
187 {
188 ParserObject *astRoot = HcsGetParserRoot();
189 if (astRoot == NULL) {
190 return EOUTPUT;
191 }
192
193 int32_t ret = EOUTPUT;
194 struct HcsFile *outputFIle = HcsOpenOutputFile(HCS_DECOMPILE_OUTPUT_FILE_SUFFIX);
195 if (outputFIle == NULL) {
196 goto OUT;
197 }
198
199 if (HcsFormatOutputWrite(HCS_DECOMPILE_FILE_HEADER) != EOK) {
200 goto OUT;
201 }
202
203 ret = HcsWalkAst(astRoot, AST_WALK_ROUND, HcsDecompileOutputWalk, HcsDecompileCloseBraceGen);
204
205 OUT:
206 HcsCloseOutput(outputFIle);
207 return ret;
208 }