]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/dll/include/boost/dll/detail/elf_info.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / dll / include / boost / dll / detail / elf_info.hpp
1 // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
2 // Copyright 2015 Antony Polukhin.
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt
6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8 #ifndef BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
9 #define BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
10
11 #include <boost/config.hpp>
12
13 #ifdef BOOST_HAS_PRAGMA_ONCE
14 # pragma once
15 #endif
16
17 #include <cstring>
18 #include <boost/filesystem/fstream.hpp>
19 #include <boost/dll/detail/x_info_interface.hpp>
20
21 namespace boost { namespace dll { namespace detail {
22
23 template <class AddressOffsetT>
24 struct Elf_Ehdr_template {
25 unsigned char e_ident[16]; /* Magic number and other info */
26 boost::uint16_t e_type; /* Object file type */
27 boost::uint16_t e_machine; /* Architecture */
28 boost::uint32_t e_version; /* Object file version */
29 AddressOffsetT e_entry; /* Entry point virtual address */
30 AddressOffsetT e_phoff; /* Program header table file offset */
31 AddressOffsetT e_shoff; /* Section header table file offset */
32 boost::uint32_t e_flags; /* Processor-specific flags */
33 boost::uint16_t e_ehsize; /* ELF header size in bytes */
34 boost::uint16_t e_phentsize; /* Program header table entry size */
35 boost::uint16_t e_phnum; /* Program header table entry count */
36 boost::uint16_t e_shentsize; /* Section header table entry size */
37 boost::uint16_t e_shnum; /* Section header table entry count */
38 boost::uint16_t e_shstrndx; /* Section header string table index */
39 };
40
41 typedef Elf_Ehdr_template<boost::uint32_t> Elf32_Ehdr_;
42 typedef Elf_Ehdr_template<boost::uint64_t> Elf64_Ehdr_;
43
44 template <class AddressOffsetT>
45 struct Elf_Shdr_template {
46 boost::uint32_t sh_name; /* Section name (string tbl index) */
47 boost::uint32_t sh_type; /* Section type */
48 AddressOffsetT sh_flags; /* Section flags */
49 AddressOffsetT sh_addr; /* Section virtual addr at execution */
50 AddressOffsetT sh_offset; /* Section file offset */
51 AddressOffsetT sh_size; /* Section size in bytes */
52 boost::uint32_t sh_link; /* Link to another section */
53 boost::uint32_t sh_info; /* Additional section information */
54 AddressOffsetT sh_addralign; /* Section alignment */
55 AddressOffsetT sh_entsize; /* Entry size if section holds table */
56 };
57
58 typedef Elf_Shdr_template<boost::uint32_t> Elf32_Shdr_;
59 typedef Elf_Shdr_template<boost::uint64_t> Elf64_Shdr_;
60
61 template <class AddressOffsetT>
62 struct Elf_Sym_template;
63
64 template <>
65 struct Elf_Sym_template<boost::uint32_t> {
66 typedef boost::uint32_t AddressOffsetT;
67
68 boost::uint32_t st_name; /* Symbol name (string tbl index) */
69 AddressOffsetT st_value; /* Symbol value */
70 AddressOffsetT st_size; /* Symbol size */
71 unsigned char st_info; /* Symbol type and binding */
72 unsigned char st_other; /* Symbol visibility */
73 boost::uint16_t st_shndx; /* Section index */
74 };
75
76 template <>
77 struct Elf_Sym_template<boost::uint64_t> {
78 typedef boost::uint64_t AddressOffsetT;
79
80 boost::uint32_t st_name; /* Symbol name (string tbl index) */
81 unsigned char st_info; /* Symbol type and binding */
82 unsigned char st_other; /* Symbol visibility */
83 boost::uint16_t st_shndx; /* Section index */
84 AddressOffsetT st_value; /* Symbol value */
85 AddressOffsetT st_size; /* Symbol size */
86 };
87
88
89 typedef Elf_Sym_template<boost::uint32_t> Elf32_Sym_;
90 typedef Elf_Sym_template<boost::uint64_t> Elf64_Sym_;
91
92 template <class AddressOffsetT>
93 class elf_info: public x_info_interface {
94 boost::filesystem::ifstream& f_;
95
96 typedef boost::dll::detail::Elf_Ehdr_template<AddressOffsetT> header_t;
97 typedef boost::dll::detail::Elf_Shdr_template<AddressOffsetT> section_t;
98 typedef boost::dll::detail::Elf_Sym_template<AddressOffsetT> symbol_t;
99
100 BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_SYMTAB_ = 2);
101 BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_STRTAB_ = 3);
102
103 BOOST_STATIC_CONSTANT(unsigned char, STB_LOCAL_ = 0); /* Local symbol */
104 BOOST_STATIC_CONSTANT(unsigned char, STB_GLOBAL_ = 1); /* Global symbol */
105 BOOST_STATIC_CONSTANT(unsigned char, STB_WEAK_ = 2); /* Weak symbol */
106
107 /* Symbol visibility specification encoded in the st_other field. */
108 BOOST_STATIC_CONSTANT(unsigned char, STV_DEFAULT_ = 0); /* Default symbol visibility rules */
109 BOOST_STATIC_CONSTANT(unsigned char, STV_INTERNAL_ = 1); /* Processor specific hidden class */
110 BOOST_STATIC_CONSTANT(unsigned char, STV_HIDDEN_ = 2); /* Sym unavailable in other modules */
111 BOOST_STATIC_CONSTANT(unsigned char, STV_PROTECTED_ = 3); /* Not preemptible, not exported */
112
113 public:
114 static bool parsing_supported(boost::filesystem::ifstream& f) {
115 const unsigned char magic_bytes[5] = {
116 0x7f, 'E', 'L', 'F', sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 1 : 2
117 };
118
119 unsigned char ch;
120 f.seekg(0);
121 for (std::size_t i = 0; i < sizeof(magic_bytes); ++i) {
122 f >> ch;
123 if (ch != magic_bytes[i]) {
124 return false;
125 }
126 }
127
128 return true;
129 }
130
131 explicit elf_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
132 : f_(f)
133 {}
134
135 std::vector<std::string> sections() {
136 std::vector<std::string> ret;
137 std::vector<char> names;
138 sections_names_raw(names);
139
140 const char* name_begin = &names[0];
141 const char* const name_end = name_begin + names.size();
142 ret.reserve(header().e_shnum);
143 do {
144 ret.push_back(name_begin);
145 name_begin += ret.back().size() + 1;
146 } while (name_begin != name_end);
147
148 return ret;
149 }
150
151 private:
152 template <class T>
153 inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
154 f_.read(reinterpret_cast<char*>(&value), size);
155 }
156
157 inline header_t header() {
158 header_t elf;
159
160 f_.seekg(0);
161 read_raw(elf);
162
163 return elf;
164 }
165
166 void sections_names_raw(std::vector<char>& sections) {
167 const header_t elf = header();
168
169 section_t section_names_section;
170 f_.seekg(elf.e_shoff + elf.e_shstrndx * sizeof(section_t));
171 read_raw(section_names_section);
172
173 sections.resize(static_cast<std::size_t>(section_names_section.sh_size));
174 f_.seekg(section_names_section.sh_offset);
175 read_raw(sections[0], static_cast<std::size_t>(section_names_section.sh_size));
176 }
177
178 void symbols_text(std::vector<symbol_t>& symbols, std::vector<char>& text) {
179 const header_t elf = header();
180 f_.seekg(elf.e_shoff);
181
182 for (std::size_t i = 0; i < elf.e_shnum; ++i) {
183 section_t section;
184 read_raw(section);
185
186 if (section.sh_type == SHT_SYMTAB_) {
187 symbols.resize(static_cast<std::size_t>(section.sh_size / sizeof(symbol_t)));
188
189 const boost::filesystem::ifstream::pos_type pos = f_.tellg();
190 f_.seekg(section.sh_offset);
191 read_raw(symbols[0], static_cast<std::size_t>(section.sh_size - (section.sh_size % sizeof(symbol_t))) );
192 f_.seekg(pos);
193 } else if (section.sh_type == SHT_STRTAB_) {
194 text.resize(static_cast<std::size_t>(section.sh_size));
195
196 const boost::filesystem::ifstream::pos_type pos = f_.tellg();
197 f_.seekg(section.sh_offset);
198 read_raw(text[0], static_cast<std::size_t>(section.sh_size));
199 f_.seekg(pos);
200 }
201 }
202 }
203
204 static bool is_visible(const symbol_t& sym) BOOST_NOEXCEPT {
205 // `(sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size` check also workarounds the
206 // GCC's issue https://sourceware.org/bugzilla/show_bug.cgi?id=13621
207 return (sym.st_other & 0x03) == STV_DEFAULT_ && (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size;
208 }
209
210 public:
211 std::vector<std::string> symbols() {
212 std::vector<std::string> ret;
213
214 std::vector<symbol_t> symbols;
215 std::vector<char> text;
216 symbols_text(symbols, text);
217
218 ret.reserve(symbols.size());
219 for (std::size_t i = 0; i < symbols.size(); ++i) {
220 if (is_visible(symbols[i])) {
221 ret.push_back(&text[0] + symbols[i].st_name);
222 if (ret.back().empty()) {
223 ret.pop_back(); // Do not show empty names
224 }
225 }
226 }
227
228 return ret;
229 }
230
231 std::vector<std::string> symbols(const char* section_name) {
232 std::vector<std::string> ret;
233
234 std::size_t index = 0;
235 std::size_t ptrs_in_section_count = 0;
236 {
237 std::vector<char> names;
238 sections_names_raw(names);
239
240 const header_t elf = header();
241
242 for (; index < elf.e_shnum; ++index) {
243 section_t section;
244 f_.seekg(elf.e_shoff + index * sizeof(section_t));
245 read_raw(section);
246
247 if (!std::strcmp(&names[0] + section.sh_name, section_name)) {
248 if (!section.sh_entsize) {
249 section.sh_entsize = 1;
250 }
251 ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize);
252 break;
253 }
254 }
255 }
256
257 std::vector<symbol_t> symbols;
258 std::vector<char> text;
259 symbols_text(symbols, text);
260
261 if (ptrs_in_section_count < symbols.size()) {
262 ret.reserve(ptrs_in_section_count);
263 } else {
264 ret.reserve(symbols.size());
265 }
266
267 for (std::size_t i = 0; i < symbols.size(); ++i) {
268 if (symbols[i].st_shndx == index && is_visible(symbols[i])) {
269 ret.push_back(&text[0] + symbols[i].st_name);
270 if (ret.back().empty()) {
271 ret.pop_back(); // Do not show empty names
272 }
273 }
274 }
275
276 return ret;
277 }
278 };
279
280 typedef elf_info<boost::uint32_t> elf_info32;
281 typedef elf_info<boost::uint64_t> elf_info64;
282
283 }}} // namespace boost::dll::detail
284
285 #endif // BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP