1 | /* |
2 | * Copyright 2012-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #ifndef FOLLY_EXPERIMENTAL_SYMBOLIZER_ELF_H_ |
18 | #error This file must be included from Elf.h |
19 | #endif |
20 | |
21 | namespace folly { |
22 | namespace symbolizer { |
23 | |
24 | template <class Fn> |
25 | const ElfPhdr* ElfFile::(Fn fn) const { |
26 | // there exist ELF binaries which execute correctly, but have invalid internal |
27 | // offset(s) to program/section headers; most probably due to invalid |
28 | // stripping of symbols |
29 | if (elfHeader().e_phoff + sizeof(ElfPhdr) >= length_) { |
30 | return nullptr; |
31 | } |
32 | |
33 | const ElfPhdr* ptr = &at<ElfPhdr>(elfHeader().e_phoff); |
34 | for (size_t i = 0; i < elfHeader().e_phnum; i++, ptr++) { |
35 | if (fn(*ptr)) { |
36 | return ptr; |
37 | } |
38 | } |
39 | return nullptr; |
40 | } |
41 | |
42 | template <class Fn> |
43 | const ElfShdr* ElfFile::iterateSections(Fn fn) const { |
44 | // there exist ELF binaries which execute correctly, but have invalid internal |
45 | // offset(s) to program/section headers; most probably due to invalid |
46 | // stripping of symbols |
47 | if (elfHeader().e_shoff + sizeof(ElfShdr) >= length_) { |
48 | return nullptr; |
49 | } |
50 | |
51 | const ElfShdr* ptr = &at<ElfShdr>(elfHeader().e_shoff); |
52 | for (size_t i = 0; i < elfHeader().e_shnum; i++, ptr++) { |
53 | if (fn(*ptr)) { |
54 | return ptr; |
55 | } |
56 | } |
57 | return nullptr; |
58 | } |
59 | |
60 | template <class Fn> |
61 | const ElfShdr* ElfFile::iterateSectionsWithType(uint32_t type, Fn fn) const { |
62 | return iterateSections( |
63 | [&](const ElfShdr& sh) { return sh.sh_type == type && fn(sh); }); |
64 | } |
65 | |
66 | template <class Fn> |
67 | const ElfShdr* ElfFile::iterateSectionsWithTypes( |
68 | std::initializer_list<uint32_t> types, |
69 | Fn fn) const { |
70 | return iterateSections([&](const ElfShdr& sh) { |
71 | auto const it = std::find(types.begin(), types.end(), sh.sh_type); |
72 | return it != types.end() && fn(sh); |
73 | }); |
74 | } |
75 | |
76 | template <class Fn> |
77 | const char* ElfFile::iterateStrings(const ElfShdr& stringTable, Fn fn) const { |
78 | validateStringTable(stringTable); |
79 | |
80 | const char* start = file_ + stringTable.sh_offset; |
81 | const char* end = start + stringTable.sh_size; |
82 | |
83 | const char* ptr = start; |
84 | while (ptr != end && !fn(ptr)) { |
85 | ptr += strlen(ptr) + 1; |
86 | } |
87 | |
88 | return ptr != end ? ptr : nullptr; |
89 | } |
90 | |
91 | template <class Fn> |
92 | const ElfSym* ElfFile::iterateSymbols(const ElfShdr& section, Fn fn) const { |
93 | FOLLY_SAFE_CHECK( |
94 | section.sh_entsize == sizeof(ElfSym), |
95 | "invalid entry size in symbol table" ); |
96 | |
97 | const ElfSym* sym = &at<ElfSym>(section.sh_offset); |
98 | const ElfSym* end = sym + (section.sh_size / section.sh_entsize); |
99 | |
100 | while (sym < end) { |
101 | if (fn(*sym)) { |
102 | return sym; |
103 | } |
104 | |
105 | ++sym; |
106 | } |
107 | |
108 | return nullptr; |
109 | } |
110 | |
111 | template <class Fn> |
112 | const ElfSym* ElfFile::iterateSymbolsWithType( |
113 | const ElfShdr& section, |
114 | uint32_t type, |
115 | Fn fn) const { |
116 | // N.B. st_info has the same representation on 32- and 64-bit platforms |
117 | return iterateSymbols(section, [&](const ElfSym& sym) -> bool { |
118 | return ELF32_ST_TYPE(sym.st_info) == type && fn(sym); |
119 | }); |
120 | } |
121 | |
122 | template <class Fn> |
123 | const ElfSym* ElfFile::iterateSymbolsWithTypes( |
124 | const ElfShdr& section, |
125 | std::initializer_list<uint32_t> types, |
126 | Fn fn) const { |
127 | // N.B. st_info has the same representation on 32- and 64-bit platforms |
128 | return iterateSymbols(section, [&](const ElfSym& sym) -> bool { |
129 | auto const elfType = ELF32_ST_TYPE(sym.st_info); |
130 | auto const it = std::find(types.begin(), types.end(), elfType); |
131 | return it != types.end() && fn(sym); |
132 | }); |
133 | } |
134 | |
135 | } // namespace symbolizer |
136 | } // namespace folly |
137 | |