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