• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "symbolTable.h"
17 
18 #include <util/helpers.h>
19 
20 namespace panda::es2panda::util {
21 const std::string SymbolTable::FIRST_LEVEL_SEPERATOR = "|";
22 const std::string SymbolTable::SECOND_LEVEL_SEPERATOR = ";";
23 const size_t FUNCTION_ITEM_NUMBER = 3;
24 const size_t MODULE_ITEM_NUMBER = 1;
25 
Initialize(int targetApiVersion,std::string targetApiSubVersion)26 bool SymbolTable::Initialize(int targetApiVersion, std::string targetApiSubVersion)
27 {
28     targetApiVersion_ = targetApiVersion;
29     targetApiSubVersion_ = targetApiSubVersion;
30     if (!symbolTable_.empty() && !ReadSymbolTable(symbolTable_)) {
31         std::cerr << "Failed to open the symbol table file'" << std::endl;
32         return false;
33     }
34 
35     if (!dumpSymbolTable_.empty()) {
36         std::fstream fs;
37         fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_),
38             std::ios_base::out | std::ios_base::trunc);
39         if (!fs.is_open()) {
40             std::cerr << "Failed to create or open the output symbol table file '"
41                       << dumpSymbolTable_ << "' during symbol table initialization." << std::endl
42                       << "This error could be due to invalid file path, lack of write permissions, "
43                       << "or the file being in use by another process." << std::endl;
44             return false;
45         }
46         fs.close();
47     }
48 
49     return true;
50 }
51 
ReadRecordHashFunctionNames(const std::string & recordName,const std::string & funcInternalName,const std::string & specialFuncIndex)52 void SymbolTable::ReadRecordHashFunctionNames(const std::string &recordName, const std::string &funcInternalName,
53                                               const std::string &specialFuncIndex)
54 {
55     auto recordHashFunctionNames = originRecordHashFunctionNames_.find(recordName);
56     if (specialFuncIndex == "0") {
57         // 0: not anonymous, special or duplicate function
58         if (recordHashFunctionNames == originRecordHashFunctionNames_.end())  {
59             std::unordered_map<std::string, std::string> functionIndexNameMap {};
60             originRecordHashFunctionNames_.insert({recordName, functionIndexNameMap});
61         }
62     } else {
63         if (recordHashFunctionNames != originRecordHashFunctionNames_.end()) {
64             recordHashFunctionNames->second.insert({specialFuncIndex, funcInternalName});
65         } else {
66             std::unordered_map<std::string, std::string> functionIndexNameMap {{specialFuncIndex, funcInternalName}};
67             originRecordHashFunctionNames_.insert({recordName, functionIndexNameMap});
68         }
69     }
70 }
71 
ReadSymbolTable(const std::string & symbolTable)72 bool SymbolTable::ReadSymbolTable(const std::string &symbolTable)
73 {
74     std::ifstream ifs;
75     std::string line;
76     ifs.open(panda::os::file::File::GetExtendedFilePath(symbolTable));
77     if (!ifs.is_open()) {
78         std::cerr << "Failed to open the symbol table file '"
79                   << symbolTable << "' during symbol table reading." << std::endl
80                   << "Please check if the file exists, the path is correct, "
81                   << "and your program has the necessary permissions to access the file." << std::endl;
82         return false;
83     }
84 
85     while (std::getline(ifs, line)) {
86         auto itemList = GetStringItems(line, FIRST_LEVEL_SEPERATOR);
87 
88         if (itemList.size() == FUNCTION_ITEM_NUMBER) {
89             // read function info
90             struct OriginFunctionInfo info(&allocator_);
91             auto funcItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR);
92             auto classItems = GetStringItems(itemList[1], SECOND_LEVEL_SEPERATOR);
93             auto lexItems = GetStringItems(itemList[2], SECOND_LEVEL_SEPERATOR);
94 
95             info.recordName = funcItems[0].substr(0, funcItems[0].find_last_of("."));
96             info.funcInternalName = funcItems[1];
97             // 2: use the third element of the function as the hash of the function
98             info.funcHash = funcItems[2];
99 
100             // 2 is to process each class name and its corresponding hash value
101             for (size_t i = 0; i < classItems.size(); i = i + 2) {
102                 info.classHash.insert(std::pair<std::string, std::string>(classItems[i], classItems[i + 1]));
103             }
104             // 3 is to process a complete lexical environment entry
105             for (size_t i = 0; i < lexItems.size(); i = i + 3) {
106                 auto name = std::string(lexItems[i]);
107                 auto slot = std::atoi(std::string(lexItems[i + 1]).c_str());
108                 auto type = std::atoi(std::string(lexItems[i + 2]).c_str());
109                 info.lexenv.insert({slot, std::pair<std::string, int>(name, type)});
110             }
111 
112             originFunctionInfo_.insert(std::pair<std::string, OriginFunctionInfo>(info.funcInternalName, info));
113             if (util::Helpers::IsDefaultApiVersion(targetApiVersion_, targetApiSubVersion_)) {
114                 // index of function in its record's special function array
115                 std::string specialFuncIndex{funcItems[3]};
116                 ReadRecordHashFunctionNames(info.recordName, info.funcInternalName, specialFuncIndex);
117             }
118         } else if (itemList.size() == MODULE_ITEM_NUMBER) {
119             // read module info
120             auto moduleItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR);
121             originModuleInfo_.insert(std::pair<std::string, std::string>(moduleItems[0], moduleItems[1]));
122         } else {
123             std::cerr << "Failed to read the symbol table line: '" << line
124                       << "' from the symbol table file '" << symbolTable << "' due to unrecognized format." << std::endl
125                       << "Please verify the format of the symbol table." << std::endl;
126         }
127     }
128     return true;
129 }
130 
FillSymbolTable(const std::stringstream & content)131 void SymbolTable::FillSymbolTable(const std::stringstream &content)
132 {
133     std::lock_guard<std::mutex> lock(m_);
134     symbolTableContent_ << content.rdbuf();
135 }
136 
WriteSymbolTable()137 void SymbolTable::WriteSymbolTable()
138 {
139     std::fstream fs;
140     fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_),
141         std::ios_base::app | std::ios_base::in);
142     if (fs.is_open()) {
143         fs << symbolTableContent_.str();
144         fs.close();
145     }
146 }
147 
GetStringItems(std::string_view input,const std::string & separator)148 std::vector<std::string_view> SymbolTable::GetStringItems(std::string_view input, const std::string &separator)
149 {
150     std::vector<std::string_view> items;
151     size_t curPos = 0;
152     size_t lastPos = 0;
153 
154     while ((curPos = input.find(separator, lastPos)) != std::string_view::npos) {
155         auto token = input.substr(lastPos, curPos - lastPos);
156         if (!token.empty()) {
157             items.push_back(token);
158         }
159         lastPos = curPos + separator.size();
160     }
161 
162     auto tail = input.substr(lastPos);
163     if (!tail.empty()) {
164         items.push_back(tail);
165     }
166 
167     return items;
168 }
169 }  // namespace panda::es2panda::util