-
Notifications
You must be signed in to change notification settings - Fork 0
/
version_builder.cc
113 lines (98 loc) · 4.24 KB
/
version_builder.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright (C) 2021 The sold authors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "version_builder.h"
#include "utils.h"
void VersionBuilder::Add(Elf_Versym versym, const std::string& soname, const std::string& version, StrtabBuilder& strtab,
const unsigned char st_info) {
// When the corresponding shared object doesn't have version information,
// we cannot help inferring it from st_info.
if (versym == NO_VERSION_INFO) {
versym = ((ELF_ST_BIND(st_info) != STB_LOCAL) ? VER_NDX_GLOBAL : VER_NDX_LOCAL);
}
if (is_special_ver_ndx(versym)) {
// TODO(joe): Consider again whether we should allow this.
// Currently, this check may fail when a symbol with nonempty soname and version is resolved by
// fallback on another symbol where is_special_ver_ndx(versym) == true in SymtabBuilder::Resolve.
// CHECK(soname.empty() && version.empty()) << " excess soname or version information is given.";
LOG(INFO) << "VersionBuilder::" << special_ver_ndx_to_str(versym);
vers.push_back(versym);
} else {
// TODO (akawashiro): Revive this assertion
// CHECK(!soname.empty() && !version.empty()) << SOLD_LOG_KEY(soname) << SOLD_LOG_KEY(version) << SOLD_LOG_KEY(versym);
auto found_filename = soname_to_filename_.find(soname);
// TODO (akawashiro): Revive this assertion
// CHECK(found_filename != soname_to_filename_.end())
// << soname << " does not exists in soname_to_filename." << SOLD_LOG_KEY(soname) << SOLD_LOG_KEY(version);
std::string filename = found_filename != soname_to_filename_.end() ? found_filename->second : "";
strtab.Add(filename);
strtab.Add(version);
if (data.find(filename) != data.end()) {
if (data[filename].find(version) != data[filename].end()) {
;
} else {
data[filename][version] = vernum;
vernum++;
}
} else {
std::map<std::string, int> ma;
ma[version] = vernum;
data[filename] = ma;
vernum++;
}
LOG(INFO) << "VersionBuilder::Add(" << data[filename][version] << ", " << soname << ", " << version << ")";
vers.push_back(data[filename][version]);
}
}
uintptr_t VersionBuilder::SizeVerneed() const {
uintptr_t s = 0;
for (const auto& m1 : data) {
s += sizeof(Elf_Verneed);
for (size_t i = 0; i < m1.second.size(); i++) {
s += sizeof(Elf_Vernaux);
}
}
return s;
}
void VersionBuilder::EmitVersym(FILE* fp) {
if (data.size() > 0) {
for (auto v : vers) {
CHECK(fwrite(&v, sizeof(v), 1, fp) == 1);
}
}
}
void VersionBuilder::EmitVerneed(FILE* fp, StrtabBuilder& strtab) {
int n_verneed = 0;
for (const auto& m1 : data) {
n_verneed++;
Elf_Verneed v;
v.vn_version = VER_NEED_CURRENT;
v.vn_cnt = m1.second.size();
v.vn_file = strtab.GetPos(m1.first);
v.vn_aux = sizeof(Elf_Verneed);
v.vn_next = (n_verneed == data.size()) ? 0 : sizeof(Elf_Verneed) + m1.second.size() * sizeof(Elf_Vernaux);
CHECK(fwrite(&v, sizeof(v), 1, fp) == 1);
int n_vernaux = 0;
for (const auto& m2 : m1.second) {
n_vernaux++;
Elf_Vernaux a;
a.vna_hash = CalcHash(m2.first);
a.vna_flags = VER_FLG_WEAK;
a.vna_other = m2.second;
a.vna_name = strtab.GetPos(m2.first);
a.vna_next = (n_vernaux == m1.second.size()) ? 0 : sizeof(Elf_Vernaux);
CHECK(fwrite(&a, sizeof(a), 1, fp) == 1);
}
}
}