• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &current, int32_t walkDepth) -> int32_t {
183             return OutPutWalk(current, walkDepth);
184         },
185         [this](std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
186             return CloseBrace(current, walkDepth);
187         })) {
188         return false;
189     }
190 
191     return file_.good();
192 }
193