• 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 <fstream>
19 #include <iostream>
20 
21 namespace panda::es2panda::util {
22 const std::string SymbolTable::FIRST_LEVEL_SEPERATOR = "|";
23 const std::string SymbolTable::SECOND_LEVEL_SEPERATOR = ";";
24 const size_t FUNCTION_ITEM_NUMBER = 3;
25 const size_t MODULE_ITEM_NUMBER = 1;
26 
Initialize()27 bool SymbolTable::Initialize()
28 {
29     if (!symbolTable_.empty() && !ReadSymbolTable(symbolTable_)) {
30         std::cerr << "Failed to read symbol table: " << symbolTable_ << ". Stop generating patch" << std::endl;
31         return false;
32     }
33 
34     if (!dumpSymbolTable_.empty()) {
35         std::fstream fs;
36         fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_),
37             std::ios_base::out | std::ios_base::trunc);
38         if (!fs.is_open()) {
39             std::cerr << "Failed to create output symbol table: " << dumpSymbolTable_ << std::endl;
40             return false;
41         }
42         fs.close();
43     }
44 
45     return true;
46 }
47 
ReadRecordHashFunctionNames(std::string recordName,std::string funcInternalName,std::string specialFuncIndex)48 void SymbolTable::ReadRecordHashFunctionNames(std::string recordName, std::string funcInternalName,
49                                               std::string specialFuncIndex)
50 {
51     auto recordHashFunctionNames = originRecordHashFunctionNames_.find(recordName);
52     if (specialFuncIndex == "0") {
53         // 0: not anonymous, special or duplicate function
54         if (recordHashFunctionNames == originRecordHashFunctionNames_.end())  {
55             std::unordered_map<std::string, std::string> functionIndexNameMap {};
56             originRecordHashFunctionNames_.insert({recordName, functionIndexNameMap});
57         }
58     } else {
59         if (recordHashFunctionNames != originRecordHashFunctionNames_.end()) {
60             recordHashFunctionNames->second.insert({specialFuncIndex, funcInternalName});
61         } else {
62             std::unordered_map<std::string, std::string> functionIndexNameMap {{specialFuncIndex, funcInternalName}};
63             originRecordHashFunctionNames_.insert({recordName, functionIndexNameMap});
64         }
65     }
66 }
67 
ReadSymbolTable(const std::string & symbolTable)68 bool SymbolTable::ReadSymbolTable(const std::string &symbolTable)
69 {
70     std::ifstream ifs;
71     std::string line;
72     ifs.open(panda::os::file::File::GetExtendedFilePath(symbolTable));
73     if (!ifs.is_open()) {
74         std::cerr << "Failed to open symbol table: " << symbolTable << std::endl;
75         return false;
76     }
77 
78     while (std::getline(ifs, line)) {
79         auto itemList = GetStringItems(line, FIRST_LEVEL_SEPERATOR);
80         if (itemList.size() == FUNCTION_ITEM_NUMBER) {
81             // read function info
82             struct OriginFunctionInfo info(&allocator_);
83             auto funcItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR);
84             auto classItems = GetStringItems(itemList[1], SECOND_LEVEL_SEPERATOR);
85             auto lexItems = GetStringItems(itemList[2], SECOND_LEVEL_SEPERATOR);
86 
87             info.recordName = funcItems[0].substr(0, funcItems[0].find_last_of("."));
88             info.funcInternalName = funcItems[1];
89             info.funcHash = funcItems[2];
90             // index of function in its record's special function array
91             std::string specialFuncIndex{funcItems[3]};
92 
93             for (size_t i = 0; i < classItems.size(); i = i + 2) {
94                 info.classHash.insert(std::pair<std::string, std::string>(classItems[i], classItems[i + 1]));
95             }
96             for (size_t i = 0; i < lexItems.size(); i = i + 3) {
97                 auto name = std::string(lexItems[i]);
98                 auto slot = std::atoi(std::string(lexItems[i + 1]).c_str());
99                 auto type = std::atoi(std::string(lexItems[i + 2]).c_str());
100                 info.lexenv.insert({slot, std::pair<std::string, int>(name, type)});
101             }
102 
103             originFunctionInfo_.insert(std::pair<std::string, OriginFunctionInfo>(info.funcInternalName, info));
104             ReadRecordHashFunctionNames(info.recordName, info.funcInternalName, specialFuncIndex);
105         } else if (itemList.size() == MODULE_ITEM_NUMBER) {
106             // read module info
107             auto moduleItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR);
108             originModuleInfo_.insert(std::pair<std::string, std::string>(moduleItems[0], moduleItems[1]));
109         } else {
110             std::cerr << "Failed to read symbol table: Unrecognized format" << std::endl;
111         }
112     }
113     return true;
114 }
115 
WriteSymbolTable(const std::string & content)116 void SymbolTable::WriteSymbolTable(const std::string &content)
117 {
118     std::lock_guard<std::mutex> lock(m_);
119     std::fstream fs;
120     fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_),
121         std::ios_base::app | std::ios_base::in);
122     if (fs.is_open()) {
123         fs << content;
124         fs.close();
125     }
126 }
127 
GetStringItems(std::string_view input,const std::string & separator)128 std::vector<std::string_view> SymbolTable::GetStringItems(std::string_view input, const std::string &separator)
129 {
130     std::vector<std::string_view> items;
131     size_t curPos = 0;
132     size_t lastPos = 0;
133 
134     while ((curPos = input.find(separator, lastPos)) != std::string_view::npos) {
135         auto token = input.substr(lastPos, curPos - lastPos);
136         if (!token.empty()) {
137             items.push_back(token);
138         }
139         lastPos = curPos + separator.size();
140     }
141 
142     auto tail = input.substr(lastPos);
143     if (!tail.empty()) {
144         items.push_back(tail);
145     }
146 
147     return items;
148 }
149 }  // namespace panda::es2panda::util