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
81 if (itemList.size() == FUNCTION_ITEM_NUMBER) {
82 // read function info
83 struct OriginFunctionInfo info(&allocator_);
84 auto funcItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR);
85 auto classItems = GetStringItems(itemList[1], SECOND_LEVEL_SEPERATOR);
86 auto lexItems = GetStringItems(itemList[2], SECOND_LEVEL_SEPERATOR);
87
88 info.recordName = funcItems[0].substr(0, funcItems[0].find_last_of("."));
89 info.funcInternalName = funcItems[1];
90 info.funcHash = funcItems[2];
91 // index of function in its record's special function array
92 std::string specialFuncIndex{funcItems[3]};
93
94 for (size_t i = 0; i < classItems.size(); i = i + 2) {
95 info.classHash.insert(std::pair<std::string, std::string>(classItems[i], classItems[i + 1]));
96 }
97 for (size_t i = 0; i < lexItems.size(); i = i + 3) {
98 auto name = std::string(lexItems[i]);
99 auto slot = std::atoi(std::string(lexItems[i + 1]).c_str());
100 auto type = std::atoi(std::string(lexItems[i + 2]).c_str());
101 info.lexenv.insert({slot, std::pair<std::string, int>(name, type)});
102 }
103
104 originFunctionInfo_.insert(std::pair<std::string, OriginFunctionInfo>(info.funcInternalName, info));
105 ReadRecordHashFunctionNames(info.recordName, info.funcInternalName, specialFuncIndex);
106 } else if (itemList.size() == MODULE_ITEM_NUMBER) {
107 // read module info
108 auto moduleItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR);
109 originModuleInfo_.insert(std::pair<std::string, std::string>(moduleItems[0], moduleItems[1]));
110 } else {
111 std::cerr << "Failed to read symbol table: Unrecognized format" << std::endl;
112 }
113 }
114 return true;
115 }
116
WriteSymbolTable(const std::string & content)117 void SymbolTable::WriteSymbolTable(const std::string &content)
118 {
119 std::lock_guard<std::mutex> lock(m_);
120 std::fstream fs;
121 fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_),
122 std::ios_base::app | std::ios_base::in);
123 if (fs.is_open()) {
124 fs << content;
125 fs.close();
126 }
127 }
128
GetStringItems(std::string_view input,const std::string & separator)129 std::vector<std::string_view> SymbolTable::GetStringItems(std::string_view input, const std::string &separator)
130 {
131 std::vector<std::string_view> items;
132 size_t curPos = 0;
133 size_t lastPos = 0;
134
135 while ((curPos = input.find(separator, lastPos)) != std::string_view::npos) {
136 auto token = input.substr(lastPos, curPos - lastPos);
137 if (!token.empty()) {
138 items.push_back(token);
139 }
140 lastPos = curPos + separator.size();
141 }
142
143 auto tail = input.substr(lastPos);
144 if (!tail.empty()) {
145 items.push_back(tail);
146 }
147
148 return items;
149 }
150 } // namespace panda::es2panda::util