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