• 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) : 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> &current, int32_t walkDepth) -> int32_t {
180             return OutPutWalk(current, walkDepth);
181         },
182         [this](std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
183             return CloseBrace(current, walkDepth);
184         })) {
185         return false;
186     }
187 
188     return file_.good();
189 }
190