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_gen.h"
10 #include "file.h"
11 #include "logger.h"
12 #include <sstream>
13
14 using namespace OHOS::Hardware;
15
DecompileGen(std::shared_ptr<Ast> ast,std::string outPutFileName)16 DecompileGen::DecompileGen(std::shared_ptr<Ast> ast, std::string outPutFileName)
17 : fileHeader_("/*\n * HDF decompile hcs file\n */\n\n"),
18 outPutFileName_(Util::File::StripSuffix(std::move(outPutFileName)).append(".d.hcs")),
19 file_(),
20 ast_(ast)
21 {
22 Logger().Debug() << "Decompile gen file: " << outPutFileName_;
23 }
24
Init()25 bool DecompileGen::Init()
26 {
27 file_.open(outPutFileName_, std::ostream::out | std::ostream::binary);
28 if (!file_.is_open()) {
29 Logger().Error() << "Failed to open decompile output file: " << outPutFileName_;
30 return false;
31 }
32 return true;
33 }
34
WriteFile(const std::string & str)35 void DecompileGen::WriteFile(const std::string &str)
36 {
37 file_ << str;
38 }
39
GetNodeRefPath(uint32_t value)40 std::string DecompileGen::GetNodeRefPath(uint32_t value)
41 {
42 std::string refPath;
43 std::shared_ptr<AstObject> astObject = ast_->GetAstRoot();
44 if (astObject == nullptr) {
45 return refPath;
46 }
47 while (astObject->Child() != nullptr) {
48 refPath = astObject->Name() + ".";
49 auto child = astObject->Child();
50 bool deepIn = false;
51 while (child != nullptr) {
52 if (child->Type() != PARSEROP_CONFNODE) {
53 child = child->Next();
54 continue;
55 }
56 if (child->GetHash() == value) {
57 return (refPath + child->Name());
58 }
59 if (value > child->GetHash() && value < (child->GetHash() + child->GetSize())) {
60 astObject = child;
61 deepIn = true;
62 break;
63 }
64 child = child->Next();
65 }
66 if (!deepIn) {
67 Logger().Error() << "ref unknown node, hash = " << value;
68 break;
69 }
70 }
71 return std::string();
72 }
73
PrintArrayType(const std::shared_ptr<AstObject> & astObj)74 int32_t DecompileGen::PrintArrayType(const std::shared_ptr<AstObject> &astObj)
75 {
76 WriteFile("[");
77 auto arrayElement = astObj->Child();
78 if (arrayElement != nullptr) {
79 while (arrayElement->Next()) {
80 if (PrintBaseType(arrayElement) != NOERR) {
81 return EOUTPUT;
82 }
83 WriteFile(", ");
84 arrayElement = arrayElement->Next();
85 }
86 if (PrintBaseType(arrayElement) != NOERR) {
87 return EOUTPUT;
88 }
89 }
90 WriteFile("]");
91 return NOERR;
92 }
93
PrintBaseType(const std::shared_ptr<AstObject> & astObj)94 int32_t DecompileGen::PrintBaseType(const std::shared_ptr<AstObject> &astObj)
95 {
96 std::stringstream outStr;
97 std::string refPath;
98 switch (astObj->Type()) {
99 case PARSEROP_UINT8:
100 case PARSEROP_UINT16:
101 case PARSEROP_UINT32:
102 case PARSEROP_UINT64:
103 outStr << "0x" << std::uppercase << std::hex << astObj->IntegerValue();
104 WriteFile(outStr.str());
105 break;
106 case PARSEROP_STRING:
107 outStr << "\"" << astObj->StringValue() << "\"";
108 WriteFile(outStr.str());
109 break;
110 case PARSEROP_NODEREF:
111 refPath = GetNodeRefPath(astObj->IntegerValue());
112 if (refPath.empty()) {
113 return EOUTPUT;
114 }
115 WriteFile("&" + refPath);
116 break;
117 case PARSEROP_ARRAY:
118 return PrintArrayType(astObj);
119 default:
120 Logger().Error() << "unknown opcode = " << astObj->Type();
121 return EFAIL;
122 }
123 return NOERR;
124 }
125
OutPutWalk(const std::shared_ptr<AstObject> & astObj,int32_t walkDepth)126 uint32_t DecompileGen::OutPutWalk(const std::shared_ptr<AstObject> &astObj, int32_t walkDepth)
127 {
128 if (astObj->Type() != PARSEROP_CONFNODE && astObj->Type() != PARSEROP_CONFTERM) {
129 return NOERR;
130 }
131 std::string tabStr = std::string(TAB_SIZE * walkDepth, ' ');
132 if (walkDepth != 0) {
133 WriteFile(tabStr);
134 }
135 std::string str;
136 switch (astObj->Type()) {
137 case PARSEROP_CONFNODE:
138 str = astObj->Name() + " {\n";
139 WriteFile(str);
140 if (astObj->Child() == nullptr) {
141 tabStr += "}\n";
142 WriteFile(tabStr);
143 }
144 break;
145 case PARSEROP_CONFTERM: {
146 str = astObj->Name() + " = ";
147 WriteFile(str);
148 int32_t ret = PrintBaseType(astObj->Child());
149 if (ret != NOERR) {
150 return ret;
151 }
152 WriteFile(";\n");
153 break;
154 }
155 default:
156 return EOUTPUT;
157 }
158 return 0;
159 }
160
CloseBrace(const std::shared_ptr<AstObject> & astObj,int32_t walkDepth)161 uint32_t DecompileGen::CloseBrace(const std::shared_ptr<AstObject> &astObj, int32_t walkDepth)
162 {
163 if (astObj->Type() != PARSEROP_CONFNODE) {
164 return NOERR;
165 }
166 std::string tabStr = std::string(TAB_SIZE * walkDepth, ' ');
167 if (astObj != ast_->GetAstRoot()) {
168 WriteFile(tabStr + "}\n");
169 } else {
170 WriteFile("}\n");
171 }
172 return file_.good() ? NOERR : EOUTPUT;
173 }
174
OutPut()175 bool DecompileGen::OutPut()
176 {
177 if (!Init()) {
178 return false;
179 }
180 WriteFile(fileHeader_);
181 if (!ast_->WalkRound(
182 [this](std::shared_ptr<AstObject> ¤t, int32_t walkDepth) -> int32_t {
183 return OutPutWalk(current, walkDepth);
184 },
185 [this](std::shared_ptr<AstObject> ¤t, int32_t walkDepth) -> int32_t {
186 return CloseBrace(current, walkDepth);
187 })) {
188 return false;
189 }
190
191 return file_.good();
192 }
193