/src/CMake/Source/cmELF.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmELF.h" |
4 | | |
5 | | #include <algorithm> |
6 | | #include <cstddef> |
7 | | #include <cstdint> |
8 | | #include <map> |
9 | | #include <memory> |
10 | | #include <sstream> |
11 | | #include <utility> |
12 | | #include <vector> |
13 | | |
14 | | #include <cm/memory> |
15 | | #include <cmext/algorithm> |
16 | | |
17 | | #include <cm3p/kwiml/abi.h> |
18 | | |
19 | | #include "cmsys/FStream.hxx" |
20 | | |
21 | | #include "cmelf/elf32.h" |
22 | | #include "cmelf/elf64.h" |
23 | | #include "cmelf/elf_common.h" |
24 | | |
25 | | // Low-level byte swapping implementation. |
26 | | template <size_t s> |
27 | | struct cmELFByteSwapSize |
28 | | { |
29 | | }; |
30 | | static void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/) |
31 | 2.52k | { |
32 | 2.52k | char one_byte; |
33 | 2.52k | one_byte = data[0]; |
34 | 2.52k | data[0] = data[1]; |
35 | 2.52k | data[1] = one_byte; |
36 | 2.52k | } |
37 | | static void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/) |
38 | 18.4M | { |
39 | 18.4M | char one_byte; |
40 | 18.4M | one_byte = data[0]; |
41 | 18.4M | data[0] = data[3]; |
42 | 18.4M | data[3] = one_byte; |
43 | 18.4M | one_byte = data[1]; |
44 | 18.4M | data[1] = data[2]; |
45 | 18.4M | data[2] = one_byte; |
46 | 18.4M | } |
47 | | static void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/) |
48 | 2.30M | { |
49 | 2.30M | char one_byte; |
50 | 2.30M | one_byte = data[0]; |
51 | 2.30M | data[0] = data[7]; |
52 | 2.30M | data[7] = one_byte; |
53 | 2.30M | one_byte = data[1]; |
54 | 2.30M | data[1] = data[6]; |
55 | 2.30M | data[6] = one_byte; |
56 | 2.30M | one_byte = data[2]; |
57 | 2.30M | data[2] = data[5]; |
58 | 2.30M | data[5] = one_byte; |
59 | 2.30M | one_byte = data[3]; |
60 | 2.30M | data[3] = data[4]; |
61 | 2.30M | data[4] = one_byte; |
62 | 2.30M | } |
63 | | |
64 | | // Low-level byte swapping interface. |
65 | | template <typename T> |
66 | | void cmELFByteSwap(T& x) |
67 | 20.7M | { |
68 | 20.7M | cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); |
69 | 20.7M | } void cmELFByteSwap<unsigned short>(unsigned short&) Line | Count | Source | 67 | 2.52k | { | 68 | 2.52k | cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); | 69 | 2.52k | } |
void cmELFByteSwap<unsigned int>(unsigned int&) Line | Count | Source | 67 | 18.3M | { | 68 | 18.3M | cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); | 69 | 18.3M | } |
void cmELFByteSwap<int>(int&) Line | Count | Source | 67 | 40.5k | { | 68 | 40.5k | cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); | 69 | 40.5k | } |
void cmELFByteSwap<unsigned long>(unsigned long&) Line | Count | Source | 67 | 2.30M | { | 68 | 2.30M | cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); | 69 | 2.30M | } |
void cmELFByteSwap<long>(long&) Line | Count | Source | 67 | 2 | { | 68 | 2 | cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); | 69 | 2 | } |
|
70 | | |
71 | | class cmELFInternal |
72 | | { |
73 | | public: |
74 | | using StringEntry = cmELF::StringEntry; |
75 | | enum ByteOrderType |
76 | | { |
77 | | ByteOrderMSB, |
78 | | ByteOrderLSB |
79 | | }; |
80 | | |
81 | | // Construct and take ownership of the file stream object. |
82 | | cmELFInternal(cmELF* external, std::unique_ptr<std::istream> fin, |
83 | | ByteOrderType order) |
84 | 1.00k | : External(external) |
85 | 1.00k | , Stream(std::move(fin)) |
86 | 1.00k | , ByteOrder(order) |
87 | 1.00k | { |
88 | | // In most cases the processor-specific byte order will match that |
89 | | // of the target execution environment. If we choose wrong here |
90 | | // it is fixed when the header is read. |
91 | 1.00k | #if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE |
92 | 1.00k | this->NeedSwap = (this->ByteOrder == ByteOrderMSB); |
93 | | #elif KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_BIG |
94 | | this->NeedSwap = (this->ByteOrder == ByteOrderLSB); |
95 | | #else |
96 | | this->NeedSwap = false; // Final decision is at runtime anyway. |
97 | | #endif |
98 | | |
99 | | // We have not yet loaded the section info. |
100 | 1.00k | this->DynamicSectionIndex = -1; |
101 | 1.00k | } |
102 | | |
103 | | // Destruct and delete the file stream object. |
104 | 1.00k | virtual ~cmELFInternal() = default; |
105 | | |
106 | | // Forward to the per-class implementation. |
107 | | virtual std::size_t GetNumberOfSections() const = 0; |
108 | | virtual unsigned long GetDynamicEntryPosition(int j) = 0; |
109 | | virtual cmELF::DynamicEntryList GetDynamicEntries() = 0; |
110 | | virtual std::vector<char> EncodeDynamicEntries( |
111 | | cmELF::DynamicEntryList const&) = 0; |
112 | | virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0; |
113 | | virtual bool IsMips() const = 0; |
114 | | virtual void PrintInfo(std::ostream& os) const = 0; |
115 | | |
116 | | /** Returns true if the ELF file has a dynamic section **/ |
117 | 7.89k | bool HasDynamicSection() const { return this->DynamicSectionIndex >= 0; } |
118 | | |
119 | | // Lookup the SONAME in the DYNAMIC section. |
120 | | StringEntry const* GetSOName() |
121 | 649 | { |
122 | 649 | return this->GetDynamicSectionString(DT_SONAME); |
123 | 649 | } |
124 | | |
125 | | // Lookup the RPATH in the DYNAMIC section. |
126 | | StringEntry const* GetRPath() |
127 | 454 | { |
128 | 454 | return this->GetDynamicSectionString(DT_RPATH); |
129 | 454 | } |
130 | | |
131 | | // Lookup the RUNPATH in the DYNAMIC section. |
132 | | StringEntry const* GetRunPath() |
133 | 302 | { |
134 | 302 | return this->GetDynamicSectionString(DT_RUNPATH); |
135 | 302 | } |
136 | | |
137 | | // Return the recorded ELF type. |
138 | 18.6k | cmELF::FileType GetFileType() const { return this->ELFType; } |
139 | | |
140 | | // Return the recorded machine. |
141 | 732 | std::uint16_t GetMachine() const { return this->Machine; } |
142 | | |
143 | | protected: |
144 | | // Data common to all ELF class implementations. |
145 | | |
146 | | // The external cmELF object. |
147 | | cmELF* External; |
148 | | |
149 | | // The stream from which to read. |
150 | | std::unique_ptr<std::istream> Stream; |
151 | | |
152 | | // The byte order of the ELF file. |
153 | | ByteOrderType ByteOrder; |
154 | | |
155 | | // The ELF file type. |
156 | | cmELF::FileType ELFType = cmELF::FileTypeInvalid; |
157 | | |
158 | | // The ELF architecture. |
159 | | std::uint16_t Machine; |
160 | | |
161 | | // Whether we need to byte-swap structures read from the stream. |
162 | | bool NeedSwap; |
163 | | |
164 | | // The section header index of the DYNAMIC section (-1 if none). |
165 | | int DynamicSectionIndex; |
166 | | |
167 | | // Helper methods for subclasses. |
168 | | void SetErrorMessage(char const* msg) |
169 | 679 | { |
170 | 679 | this->External->ErrorMessage = msg; |
171 | 679 | this->ELFType = cmELF::FileTypeInvalid; |
172 | 679 | } |
173 | | |
174 | | // Store string table entry states. |
175 | | std::map<unsigned int, StringEntry> DynamicSectionStrings; |
176 | | }; |
177 | | |
178 | | // Configure the implementation template for 32-bit ELF files. |
179 | | struct cmELFTypes32 |
180 | | { |
181 | | using ELF_Ehdr = Elf32_Ehdr; |
182 | | using ELF_Shdr = Elf32_Shdr; |
183 | | using ELF_Dyn = Elf32_Dyn; |
184 | | using ELF_Half = Elf32_Half; |
185 | | using tagtype = ::uint32_t; |
186 | 199 | static char const* GetName() { return "32-bit"; } |
187 | | }; |
188 | | |
189 | | // Configure the implementation template for 64-bit ELF files. |
190 | | struct cmELFTypes64 |
191 | | { |
192 | | using ELF_Ehdr = Elf64_Ehdr; |
193 | | using ELF_Shdr = Elf64_Shdr; |
194 | | using ELF_Dyn = Elf64_Dyn; |
195 | | using ELF_Half = Elf64_Half; |
196 | | using tagtype = ::uint64_t; |
197 | 128 | static char const* GetName() { return "64-bit"; } |
198 | | }; |
199 | | |
200 | | // Parser implementation template. |
201 | | template <class Types> |
202 | | class cmELFInternalImpl : public cmELFInternal |
203 | | { |
204 | | public: |
205 | | // Copy the ELF file format types from our configuration parameter. |
206 | | using ELF_Ehdr = typename Types::ELF_Ehdr; |
207 | | using ELF_Shdr = typename Types::ELF_Shdr; |
208 | | using ELF_Dyn = typename Types::ELF_Dyn; |
209 | | using ELF_Half = typename Types::ELF_Half; |
210 | | using tagtype = typename Types::tagtype; |
211 | | |
212 | | // Construct with a stream and byte swap indicator. |
213 | | cmELFInternalImpl(cmELF* external, std::unique_ptr<std::istream> fin, |
214 | | ByteOrderType order); |
215 | | |
216 | | // Return the number of sections as specified by the ELF header. |
217 | | std::size_t GetNumberOfSections() const override |
218 | 1.64k | { |
219 | 1.64k | return static_cast<unsigned int>(this->ELFHeader.e_shnum + |
220 | 1.64k | this->SectionHeaders[0].sh_size); |
221 | 1.64k | } cmELFInternalImpl<cmELFTypes32>::GetNumberOfSections() const Line | Count | Source | 218 | 811 | { | 219 | 811 | return static_cast<unsigned int>(this->ELFHeader.e_shnum + | 220 | 811 | this->SectionHeaders[0].sh_size); | 221 | 811 | } |
cmELFInternalImpl<cmELFTypes64>::GetNumberOfSections() const Line | Count | Source | 218 | 837 | { | 219 | 837 | return static_cast<unsigned int>(this->ELFHeader.e_shnum + | 220 | 837 | this->SectionHeaders[0].sh_size); | 221 | 837 | } |
|
222 | | |
223 | | // Get the file position of a dynamic section entry. |
224 | | unsigned long GetDynamicEntryPosition(int j) override; |
225 | | |
226 | | cmELF::DynamicEntryList GetDynamicEntries() override; |
227 | | std::vector<char> EncodeDynamicEntries( |
228 | | cmELF::DynamicEntryList const&) override; |
229 | | |
230 | | // Lookup a string from the dynamic section with the given tag. |
231 | | StringEntry const* GetDynamicSectionString(unsigned int tag) override; |
232 | | |
233 | 732 | bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; }cmELFInternalImpl<cmELFTypes32>::IsMips() const Line | Count | Source | 233 | 355 | bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } |
cmELFInternalImpl<cmELFTypes64>::IsMips() const Line | Count | Source | 233 | 377 | bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } |
|
234 | | |
235 | | // Print information about the ELF file. |
236 | | void PrintInfo(std::ostream& os) const override |
237 | 327 | { |
238 | 327 | os << "ELF " << Types::GetName(); |
239 | 327 | if (this->ByteOrder == ByteOrderMSB) { |
240 | 77 | os << " MSB"; |
241 | 250 | } else if (this->ByteOrder == ByteOrderLSB) { |
242 | 250 | os << " LSB"; |
243 | 250 | } |
244 | 327 | switch (this->ELFType) { |
245 | 0 | case cmELF::FileTypeInvalid: |
246 | 0 | os << " invalid file"; |
247 | 0 | break; |
248 | 10 | case cmELF::FileTypeRelocatableObject: |
249 | 10 | os << " relocatable object"; |
250 | 10 | break; |
251 | 46 | case cmELF::FileTypeExecutable: |
252 | 46 | os << " executable"; |
253 | 46 | break; |
254 | 182 | case cmELF::FileTypeSharedLibrary: |
255 | 182 | os << " shared library"; |
256 | 182 | break; |
257 | 10 | case cmELF::FileTypeCore: |
258 | 10 | os << " core file"; |
259 | 10 | break; |
260 | 26 | case cmELF::FileTypeSpecificOS: |
261 | 26 | os << " os-specific type"; |
262 | 26 | break; |
263 | 53 | case cmELF::FileTypeSpecificProc: |
264 | 53 | os << " processor-specific type"; |
265 | 53 | break; |
266 | 327 | } |
267 | 327 | os << "\n"; |
268 | 327 | } cmELFInternalImpl<cmELFTypes32>::PrintInfo(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const Line | Count | Source | 237 | 199 | { | 238 | 199 | os << "ELF " << Types::GetName(); | 239 | 199 | if (this->ByteOrder == ByteOrderMSB) { | 240 | 64 | os << " MSB"; | 241 | 135 | } else if (this->ByteOrder == ByteOrderLSB) { | 242 | 135 | os << " LSB"; | 243 | 135 | } | 244 | 199 | switch (this->ELFType) { | 245 | 0 | case cmELF::FileTypeInvalid: | 246 | 0 | os << " invalid file"; | 247 | 0 | break; | 248 | 4 | case cmELF::FileTypeRelocatableObject: | 249 | 4 | os << " relocatable object"; | 250 | 4 | break; | 251 | 17 | case cmELF::FileTypeExecutable: | 252 | 17 | os << " executable"; | 253 | 17 | break; | 254 | 122 | case cmELF::FileTypeSharedLibrary: | 255 | 122 | os << " shared library"; | 256 | 122 | break; | 257 | 7 | case cmELF::FileTypeCore: | 258 | 7 | os << " core file"; | 259 | 7 | break; | 260 | 16 | case cmELF::FileTypeSpecificOS: | 261 | 16 | os << " os-specific type"; | 262 | 16 | break; | 263 | 33 | case cmELF::FileTypeSpecificProc: | 264 | 33 | os << " processor-specific type"; | 265 | 33 | break; | 266 | 199 | } | 267 | 199 | os << "\n"; | 268 | 199 | } |
cmELFInternalImpl<cmELFTypes64>::PrintInfo(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const Line | Count | Source | 237 | 128 | { | 238 | 128 | os << "ELF " << Types::GetName(); | 239 | 128 | if (this->ByteOrder == ByteOrderMSB) { | 240 | 13 | os << " MSB"; | 241 | 115 | } else if (this->ByteOrder == ByteOrderLSB) { | 242 | 115 | os << " LSB"; | 243 | 115 | } | 244 | 128 | switch (this->ELFType) { | 245 | 0 | case cmELF::FileTypeInvalid: | 246 | 0 | os << " invalid file"; | 247 | 0 | break; | 248 | 6 | case cmELF::FileTypeRelocatableObject: | 249 | 6 | os << " relocatable object"; | 250 | 6 | break; | 251 | 29 | case cmELF::FileTypeExecutable: | 252 | 29 | os << " executable"; | 253 | 29 | break; | 254 | 60 | case cmELF::FileTypeSharedLibrary: | 255 | 60 | os << " shared library"; | 256 | 60 | break; | 257 | 3 | case cmELF::FileTypeCore: | 258 | 3 | os << " core file"; | 259 | 3 | break; | 260 | 10 | case cmELF::FileTypeSpecificOS: | 261 | 10 | os << " os-specific type"; | 262 | 10 | break; | 263 | 20 | case cmELF::FileTypeSpecificProc: | 264 | 20 | os << " processor-specific type"; | 265 | 20 | break; | 266 | 128 | } | 267 | 128 | os << "\n"; | 268 | 128 | } |
|
269 | | |
270 | | private: |
271 | | static_assert(sizeof(ELF_Dyn().d_un.d_val) == sizeof(ELF_Dyn().d_un.d_ptr), |
272 | | "ByteSwap(ELF_Dyn) assumes d_val and d_ptr are the same size"); |
273 | | |
274 | | void ByteSwap(ELF_Ehdr& elf_header) |
275 | 264 | { |
276 | 264 | cmELFByteSwap(elf_header.e_type); |
277 | 264 | cmELFByteSwap(elf_header.e_machine); |
278 | 264 | cmELFByteSwap(elf_header.e_version); |
279 | 264 | cmELFByteSwap(elf_header.e_entry); |
280 | 264 | cmELFByteSwap(elf_header.e_phoff); |
281 | 264 | cmELFByteSwap(elf_header.e_shoff); |
282 | 264 | cmELFByteSwap(elf_header.e_flags); |
283 | 264 | cmELFByteSwap(elf_header.e_ehsize); |
284 | 264 | cmELFByteSwap(elf_header.e_phentsize); |
285 | 264 | cmELFByteSwap(elf_header.e_phnum); |
286 | 264 | cmELFByteSwap(elf_header.e_shentsize); |
287 | 264 | cmELFByteSwap(elf_header.e_shnum); |
288 | 264 | cmELFByteSwap(elf_header.e_shstrndx); |
289 | 264 | } cmELFInternalImpl<cmELFTypes32>::ByteSwap(Elf32_Ehdr&) Line | Count | Source | 275 | 213 | { | 276 | 213 | cmELFByteSwap(elf_header.e_type); | 277 | 213 | cmELFByteSwap(elf_header.e_machine); | 278 | 213 | cmELFByteSwap(elf_header.e_version); | 279 | 213 | cmELFByteSwap(elf_header.e_entry); | 280 | 213 | cmELFByteSwap(elf_header.e_phoff); | 281 | 213 | cmELFByteSwap(elf_header.e_shoff); | 282 | 213 | cmELFByteSwap(elf_header.e_flags); | 283 | 213 | cmELFByteSwap(elf_header.e_ehsize); | 284 | 213 | cmELFByteSwap(elf_header.e_phentsize); | 285 | 213 | cmELFByteSwap(elf_header.e_phnum); | 286 | 213 | cmELFByteSwap(elf_header.e_shentsize); | 287 | 213 | cmELFByteSwap(elf_header.e_shnum); | 288 | 213 | cmELFByteSwap(elf_header.e_shstrndx); | 289 | 213 | } |
cmELFInternalImpl<cmELFTypes64>::ByteSwap(Elf64_Ehdr&) Line | Count | Source | 275 | 51 | { | 276 | 51 | cmELFByteSwap(elf_header.e_type); | 277 | 51 | cmELFByteSwap(elf_header.e_machine); | 278 | 51 | cmELFByteSwap(elf_header.e_version); | 279 | 51 | cmELFByteSwap(elf_header.e_entry); | 280 | 51 | cmELFByteSwap(elf_header.e_phoff); | 281 | 51 | cmELFByteSwap(elf_header.e_shoff); | 282 | 51 | cmELFByteSwap(elf_header.e_flags); | 283 | 51 | cmELFByteSwap(elf_header.e_ehsize); | 284 | 51 | cmELFByteSwap(elf_header.e_phentsize); | 285 | 51 | cmELFByteSwap(elf_header.e_phnum); | 286 | 51 | cmELFByteSwap(elf_header.e_shentsize); | 287 | 51 | cmELFByteSwap(elf_header.e_shnum); | 288 | 51 | cmELFByteSwap(elf_header.e_shstrndx); | 289 | 51 | } |
|
290 | | |
291 | | void ByteSwap(ELF_Shdr& sec_header) |
292 | 2.06M | { |
293 | 2.06M | cmELFByteSwap(sec_header.sh_name); |
294 | 2.06M | cmELFByteSwap(sec_header.sh_type); |
295 | 2.06M | cmELFByteSwap(sec_header.sh_flags); |
296 | 2.06M | cmELFByteSwap(sec_header.sh_addr); |
297 | 2.06M | cmELFByteSwap(sec_header.sh_offset); |
298 | 2.06M | cmELFByteSwap(sec_header.sh_size); |
299 | 2.06M | cmELFByteSwap(sec_header.sh_link); |
300 | 2.06M | cmELFByteSwap(sec_header.sh_info); |
301 | 2.06M | cmELFByteSwap(sec_header.sh_addralign); |
302 | 2.06M | cmELFByteSwap(sec_header.sh_entsize); |
303 | 2.06M | } cmELFInternalImpl<cmELFTypes32>::ByteSwap(Elf32_Shdr&) Line | Count | Source | 292 | 1.68M | { | 293 | 1.68M | cmELFByteSwap(sec_header.sh_name); | 294 | 1.68M | cmELFByteSwap(sec_header.sh_type); | 295 | 1.68M | cmELFByteSwap(sec_header.sh_flags); | 296 | 1.68M | cmELFByteSwap(sec_header.sh_addr); | 297 | 1.68M | cmELFByteSwap(sec_header.sh_offset); | 298 | 1.68M | cmELFByteSwap(sec_header.sh_size); | 299 | 1.68M | cmELFByteSwap(sec_header.sh_link); | 300 | 1.68M | cmELFByteSwap(sec_header.sh_info); | 301 | 1.68M | cmELFByteSwap(sec_header.sh_addralign); | 302 | 1.68M | cmELFByteSwap(sec_header.sh_entsize); | 303 | 1.68M | } |
cmELFInternalImpl<cmELFTypes64>::ByteSwap(Elf64_Shdr&) Line | Count | Source | 292 | 384k | { | 293 | 384k | cmELFByteSwap(sec_header.sh_name); | 294 | 384k | cmELFByteSwap(sec_header.sh_type); | 295 | 384k | cmELFByteSwap(sec_header.sh_flags); | 296 | 384k | cmELFByteSwap(sec_header.sh_addr); | 297 | 384k | cmELFByteSwap(sec_header.sh_offset); | 298 | 384k | cmELFByteSwap(sec_header.sh_size); | 299 | 384k | cmELFByteSwap(sec_header.sh_link); | 300 | 384k | cmELFByteSwap(sec_header.sh_info); | 301 | 384k | cmELFByteSwap(sec_header.sh_addralign); | 302 | 384k | cmELFByteSwap(sec_header.sh_entsize); | 303 | 384k | } |
|
304 | | |
305 | | void ByteSwap(ELF_Dyn& dyn) |
306 | 40.5k | { |
307 | 40.5k | cmELFByteSwap(dyn.d_tag); |
308 | 40.5k | cmELFByteSwap(dyn.d_un.d_val); |
309 | 40.5k | } cmELFInternalImpl<cmELFTypes32>::ByteSwap(Elf32_Dyn&) Line | Count | Source | 306 | 40.5k | { | 307 | 40.5k | cmELFByteSwap(dyn.d_tag); | 308 | 40.5k | cmELFByteSwap(dyn.d_un.d_val); | 309 | 40.5k | } |
cmELFInternalImpl<cmELFTypes64>::ByteSwap(Elf64_Dyn&) Line | Count | Source | 306 | 2 | { | 307 | 2 | cmELFByteSwap(dyn.d_tag); | 308 | 2 | cmELFByteSwap(dyn.d_un.d_val); | 309 | 2 | } |
|
310 | | |
311 | | bool FileTypeValid(ELF_Half et) |
312 | 1.16k | { |
313 | 1.16k | unsigned int eti = static_cast<unsigned int>(et); |
314 | 1.16k | if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN || |
315 | 737 | eti == ET_CORE) { |
316 | 737 | return true; |
317 | 737 | } |
318 | 431 | if (eti >= ET_LOOS && eti <= ET_HIOS) { |
319 | 58 | return true; |
320 | 58 | } |
321 | 373 | if (eti >= ET_LOPROC && eti <= ET_HIPROC) { |
322 | 155 | return true; |
323 | 155 | } |
324 | 218 | return false; |
325 | 373 | } cmELFInternalImpl<cmELFTypes32>::FileTypeValid(unsigned short) Line | Count | Source | 312 | 593 | { | 313 | 593 | unsigned int eti = static_cast<unsigned int>(et); | 314 | 593 | if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN || | 315 | 338 | eti == ET_CORE) { | 316 | 338 | return true; | 317 | 338 | } | 318 | 255 | if (eti >= ET_LOOS && eti <= ET_HIOS) { | 319 | 39 | return true; | 320 | 39 | } | 321 | 216 | if (eti >= ET_LOPROC && eti <= ET_HIPROC) { | 322 | 98 | return true; | 323 | 98 | } | 324 | 118 | return false; | 325 | 216 | } |
cmELFInternalImpl<cmELFTypes64>::FileTypeValid(unsigned short) Line | Count | Source | 312 | 575 | { | 313 | 575 | unsigned int eti = static_cast<unsigned int>(et); | 314 | 575 | if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN || | 315 | 399 | eti == ET_CORE) { | 316 | 399 | return true; | 317 | 399 | } | 318 | 176 | if (eti >= ET_LOOS && eti <= ET_HIOS) { | 319 | 19 | return true; | 320 | 19 | } | 321 | 157 | if (eti >= ET_LOPROC && eti <= ET_HIPROC) { | 322 | 57 | return true; | 323 | 57 | } | 324 | 100 | return false; | 325 | 157 | } |
|
326 | | |
327 | | bool Read(ELF_Ehdr& x) |
328 | 1.00k | { |
329 | | // Read the header from the file. |
330 | 1.00k | if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) { |
331 | 4 | return false; |
332 | 4 | } |
333 | | |
334 | | // The byte order of ELF header fields may not match that of the |
335 | | // processor-specific data. The header fields are ordered to |
336 | | // match the target execution environment, so we may need to |
337 | | // memorize the order of all platforms based on the e_machine |
338 | | // value. As a heuristic, if the type is invalid but its |
339 | | // swapped value is okay then flip our swap mode. |
340 | 1.00k | ELF_Half et = x.e_type; |
341 | 1.00k | if (this->NeedSwap) { |
342 | 244 | cmELFByteSwap(et); |
343 | 244 | } |
344 | 1.00k | if (!this->FileTypeValid(et)) { |
345 | 166 | cmELFByteSwap(et); |
346 | 166 | if (this->FileTypeValid(et)) { |
347 | | // The previous byte order guess was wrong. Flip it. |
348 | 114 | this->NeedSwap = !this->NeedSwap; |
349 | 114 | } |
350 | 166 | } |
351 | | |
352 | | // Fix the byte order of the header. |
353 | 1.00k | if (this->NeedSwap) { |
354 | 264 | this->ByteSwap(x); |
355 | 264 | } |
356 | 1.00k | return true; |
357 | 1.00k | } cmELFInternalImpl<cmELFTypes32>::Read(Elf32_Ehdr&) Line | Count | Source | 328 | 505 | { | 329 | | // Read the header from the file. | 330 | 505 | if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) { | 331 | 2 | return false; | 332 | 2 | } | 333 | | | 334 | | // The byte order of ELF header fields may not match that of the | 335 | | // processor-specific data. The header fields are ordered to | 336 | | // match the target execution environment, so we may need to | 337 | | // memorize the order of all platforms based on the e_machine | 338 | | // value. As a heuristic, if the type is invalid but its | 339 | | // swapped value is okay then flip our swap mode. | 340 | 503 | ELF_Half et = x.e_type; | 341 | 503 | if (this->NeedSwap) { | 342 | 211 | cmELFByteSwap(et); | 343 | 211 | } | 344 | 503 | if (!this->FileTypeValid(et)) { | 345 | 90 | cmELFByteSwap(et); | 346 | 90 | if (this->FileTypeValid(et)) { | 347 | | // The previous byte order guess was wrong. Flip it. | 348 | 62 | this->NeedSwap = !this->NeedSwap; | 349 | 62 | } | 350 | 90 | } | 351 | | | 352 | | // Fix the byte order of the header. | 353 | 503 | if (this->NeedSwap) { | 354 | 213 | this->ByteSwap(x); | 355 | 213 | } | 356 | 503 | return true; | 357 | 505 | } |
cmELFInternalImpl<cmELFTypes64>::Read(Elf64_Ehdr&) Line | Count | Source | 328 | 501 | { | 329 | | // Read the header from the file. | 330 | 501 | if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) { | 331 | 2 | return false; | 332 | 2 | } | 333 | | | 334 | | // The byte order of ELF header fields may not match that of the | 335 | | // processor-specific data. The header fields are ordered to | 336 | | // match the target execution environment, so we may need to | 337 | | // memorize the order of all platforms based on the e_machine | 338 | | // value. As a heuristic, if the type is invalid but its | 339 | | // swapped value is okay then flip our swap mode. | 340 | 499 | ELF_Half et = x.e_type; | 341 | 499 | if (this->NeedSwap) { | 342 | 33 | cmELFByteSwap(et); | 343 | 33 | } | 344 | 499 | if (!this->FileTypeValid(et)) { | 345 | 76 | cmELFByteSwap(et); | 346 | 76 | if (this->FileTypeValid(et)) { | 347 | | // The previous byte order guess was wrong. Flip it. | 348 | 52 | this->NeedSwap = !this->NeedSwap; | 349 | 52 | } | 350 | 76 | } | 351 | | | 352 | | // Fix the byte order of the header. | 353 | 499 | if (this->NeedSwap) { | 354 | 51 | this->ByteSwap(x); | 355 | 51 | } | 356 | 499 | return true; | 357 | 501 | } |
|
358 | | bool Read(ELF_Shdr& x) |
359 | 18.8M | { |
360 | 18.8M | if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && |
361 | 18.8M | this->NeedSwap) { |
362 | 2.06M | this->ByteSwap(x); |
363 | 2.06M | } |
364 | 18.8M | return !this->Stream->fail(); |
365 | 18.8M | } cmELFInternalImpl<cmELFTypes32>::Read(Elf32_Shdr&) Line | Count | Source | 359 | 16.5M | { | 360 | 16.5M | if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && | 361 | 16.5M | this->NeedSwap) { | 362 | 1.68M | this->ByteSwap(x); | 363 | 1.68M | } | 364 | 16.5M | return !this->Stream->fail(); | 365 | 16.5M | } |
cmELFInternalImpl<cmELFTypes64>::Read(Elf64_Shdr&) Line | Count | Source | 359 | 2.26M | { | 360 | 2.26M | if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && | 361 | 2.26M | this->NeedSwap) { | 362 | 384k | this->ByteSwap(x); | 363 | 384k | } | 364 | 2.26M | return !this->Stream->fail(); | 365 | 2.26M | } |
|
366 | | bool Read(ELF_Dyn& x) |
367 | 100k | { |
368 | 100k | if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && |
369 | 100k | this->NeedSwap) { |
370 | 22.9k | this->ByteSwap(x); |
371 | 22.9k | } |
372 | 100k | return !this->Stream->fail(); |
373 | 100k | } cmELFInternalImpl<cmELFTypes32>::Read(Elf32_Dyn&) Line | Count | Source | 367 | 91.2k | { | 368 | 91.2k | if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && | 369 | 91.1k | this->NeedSwap) { | 370 | 22.8k | this->ByteSwap(x); | 371 | 22.8k | } | 372 | 91.2k | return !this->Stream->fail(); | 373 | 91.2k | } |
cmELFInternalImpl<cmELFTypes64>::Read(Elf64_Dyn&) Line | Count | Source | 367 | 9.56k | { | 368 | 9.56k | if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && | 369 | 9.52k | this->NeedSwap) { | 370 | 1 | this->ByteSwap(x); | 371 | 1 | } | 372 | 9.56k | return !this->Stream->fail(); | 373 | 9.56k | } |
|
374 | | |
375 | | bool LoadSectionHeader(std::size_t i) |
376 | 18.8M | { |
377 | | // Read the section header from the file. |
378 | 18.8M | this->Stream->seekg(this->ELFHeader.e_shoff + |
379 | 18.8M | this->ELFHeader.e_shentsize * i); |
380 | 18.8M | if (!this->Read(this->SectionHeaders[i])) { |
381 | 216 | this->SetErrorMessage("Failed to load section headers."); |
382 | 216 | return false; |
383 | 216 | } |
384 | | |
385 | | // Identify some important sections. |
386 | 18.8M | if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) { |
387 | 12.5M | this->DynamicSectionIndex = static_cast<int>(i); |
388 | 12.5M | } |
389 | 18.8M | return true; |
390 | 18.8M | } cmELFInternalImpl<cmELFTypes32>::LoadSectionHeader(unsigned long) Line | Count | Source | 376 | 16.5M | { | 377 | | // Read the section header from the file. | 378 | 16.5M | this->Stream->seekg(this->ELFHeader.e_shoff + | 379 | 16.5M | this->ELFHeader.e_shentsize * i); | 380 | 16.5M | if (!this->Read(this->SectionHeaders[i])) { | 381 | 119 | this->SetErrorMessage("Failed to load section headers."); | 382 | 119 | return false; | 383 | 119 | } | 384 | | | 385 | | // Identify some important sections. | 386 | 16.5M | if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) { | 387 | 12.5M | this->DynamicSectionIndex = static_cast<int>(i); | 388 | 12.5M | } | 389 | 16.5M | return true; | 390 | 16.5M | } |
cmELFInternalImpl<cmELFTypes64>::LoadSectionHeader(unsigned long) Line | Count | Source | 376 | 2.26M | { | 377 | | // Read the section header from the file. | 378 | 2.26M | this->Stream->seekg(this->ELFHeader.e_shoff + | 379 | 2.26M | this->ELFHeader.e_shentsize * i); | 380 | 2.26M | if (!this->Read(this->SectionHeaders[i])) { | 381 | 97 | this->SetErrorMessage("Failed to load section headers."); | 382 | 97 | return false; | 383 | 97 | } | 384 | | | 385 | | // Identify some important sections. | 386 | 2.26M | if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) { | 387 | 605 | this->DynamicSectionIndex = static_cast<int>(i); | 388 | 605 | } | 389 | 2.26M | return true; | 390 | 2.26M | } |
|
391 | | |
392 | | bool LoadDynamicSection(); |
393 | | |
394 | | // Store the main ELF header. |
395 | | ELF_Ehdr ELFHeader; |
396 | | |
397 | | // Store all the section headers. |
398 | | std::vector<ELF_Shdr> SectionHeaders; |
399 | | |
400 | | // Store all entries of the DYNAMIC section. |
401 | | std::vector<ELF_Dyn> DynamicSectionEntries; |
402 | | }; |
403 | | |
404 | | template <class Types> |
405 | | cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external, |
406 | | std::unique_ptr<std::istream> fin, |
407 | | ByteOrderType order) |
408 | 1.00k | : cmELFInternal(external, std::move(fin), order) |
409 | 1.00k | { |
410 | | // Read the main header. |
411 | 1.00k | if (!this->Read(this->ELFHeader)) { |
412 | 4 | this->SetErrorMessage("Failed to read main ELF header."); |
413 | 4 | return; |
414 | 4 | } |
415 | | |
416 | | // Determine the ELF file type. |
417 | 1.00k | switch (this->ELFHeader.e_type) { |
418 | 2 | case ET_NONE: |
419 | 2 | this->SetErrorMessage("ELF file type is NONE."); |
420 | 2 | return; |
421 | 29 | case ET_REL: |
422 | 29 | this->ELFType = cmELF::FileTypeRelocatableObject; |
423 | 29 | break; |
424 | 243 | case ET_EXEC: |
425 | 243 | this->ELFType = cmELF::FileTypeExecutable; |
426 | 243 | break; |
427 | 428 | case ET_DYN: |
428 | 428 | this->ELFType = cmELF::FileTypeSharedLibrary; |
429 | 428 | break; |
430 | 35 | case ET_CORE: |
431 | 35 | this->ELFType = cmELF::FileTypeCore; |
432 | 35 | break; |
433 | 265 | default: { |
434 | 265 | unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); |
435 | 265 | if (eti >= ET_LOOS && eti <= ET_HIOS) { |
436 | 58 | this->ELFType = cmELF::FileTypeSpecificOS; |
437 | 58 | break; |
438 | 58 | } |
439 | 207 | if (eti >= ET_LOPROC && eti <= ET_HIPROC) { |
440 | 155 | this->ELFType = cmELF::FileTypeSpecificProc; |
441 | 155 | break; |
442 | 155 | } |
443 | 52 | std::ostringstream e; |
444 | 52 | e << "Unknown ELF file type " << eti; |
445 | 52 | this->SetErrorMessage(e.str().c_str()); |
446 | 52 | return; |
447 | 207 | } |
448 | 1.00k | } |
449 | | |
450 | 948 | this->Machine = this->ELFHeader.e_machine; |
451 | | |
452 | | // Load the section headers. |
453 | 948 | std::size_t const minSections = 1; |
454 | 948 | std::size_t numSections = this->ELFHeader.e_shnum; |
455 | 948 | this->SectionHeaders.resize(std::max(numSections, minSections)); |
456 | 948 | if (!this->LoadSectionHeader(0)) { |
457 | 32 | return; |
458 | 32 | } |
459 | 916 | numSections = this->GetNumberOfSections(); |
460 | 916 | this->SectionHeaders.resize(std::max(numSections, minSections)); |
461 | 18.8M | for (std::size_t i = 1; i < numSections; ++i) { |
462 | 18.8M | if (!this->LoadSectionHeader(i)) { |
463 | 184 | return; |
464 | 184 | } |
465 | 18.8M | } |
466 | 916 | } cmELFInternalImpl<cmELFTypes32>::cmELFInternalImpl(cmELF*, std::__1::unique_ptr<std::__1::basic_istream<char, std::__1::char_traits<char> >, std::__1::default_delete<std::__1::basic_istream<char, std::__1::char_traits<char> > > >, cmELFInternal::ByteOrderType) Line | Count | Source | 408 | 505 | : cmELFInternal(external, std::move(fin), order) | 409 | 505 | { | 410 | | // Read the main header. | 411 | 505 | if (!this->Read(this->ELFHeader)) { | 412 | 2 | this->SetErrorMessage("Failed to read main ELF header."); | 413 | 2 | return; | 414 | 2 | } | 415 | | | 416 | | // Determine the ELF file type. | 417 | 503 | switch (this->ELFHeader.e_type) { | 418 | 1 | case ET_NONE: | 419 | 1 | this->SetErrorMessage("ELF file type is NONE."); | 420 | 1 | return; | 421 | 16 | case ET_REL: | 422 | 16 | this->ELFType = cmELF::FileTypeRelocatableObject; | 423 | 16 | break; | 424 | 35 | case ET_EXEC: | 425 | 35 | this->ELFType = cmELF::FileTypeExecutable; | 426 | 35 | break; | 427 | 260 | case ET_DYN: | 428 | 260 | this->ELFType = cmELF::FileTypeSharedLibrary; | 429 | 260 | break; | 430 | 26 | case ET_CORE: | 431 | 26 | this->ELFType = cmELF::FileTypeCore; | 432 | 26 | break; | 433 | 165 | default: { | 434 | 165 | unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); | 435 | 165 | if (eti >= ET_LOOS && eti <= ET_HIOS) { | 436 | 39 | this->ELFType = cmELF::FileTypeSpecificOS; | 437 | 39 | break; | 438 | 39 | } | 439 | 126 | if (eti >= ET_LOPROC && eti <= ET_HIPROC) { | 440 | 98 | this->ELFType = cmELF::FileTypeSpecificProc; | 441 | 98 | break; | 442 | 98 | } | 443 | 28 | std::ostringstream e; | 444 | 28 | e << "Unknown ELF file type " << eti; | 445 | 28 | this->SetErrorMessage(e.str().c_str()); | 446 | 28 | return; | 447 | 126 | } | 448 | 503 | } | 449 | | | 450 | 474 | this->Machine = this->ELFHeader.e_machine; | 451 | | | 452 | | // Load the section headers. | 453 | 474 | std::size_t const minSections = 1; | 454 | 474 | std::size_t numSections = this->ELFHeader.e_shnum; | 455 | 474 | this->SectionHeaders.resize(std::max(numSections, minSections)); | 456 | 474 | if (!this->LoadSectionHeader(0)) { | 457 | 18 | return; | 458 | 18 | } | 459 | 456 | numSections = this->GetNumberOfSections(); | 460 | 456 | this->SectionHeaders.resize(std::max(numSections, minSections)); | 461 | 16.5M | for (std::size_t i = 1; i < numSections; ++i) { | 462 | 16.5M | if (!this->LoadSectionHeader(i)) { | 463 | 101 | return; | 464 | 101 | } | 465 | 16.5M | } | 466 | 456 | } |
cmELFInternalImpl<cmELFTypes64>::cmELFInternalImpl(cmELF*, std::__1::unique_ptr<std::__1::basic_istream<char, std::__1::char_traits<char> >, std::__1::default_delete<std::__1::basic_istream<char, std::__1::char_traits<char> > > >, cmELFInternal::ByteOrderType) Line | Count | Source | 408 | 501 | : cmELFInternal(external, std::move(fin), order) | 409 | 501 | { | 410 | | // Read the main header. | 411 | 501 | if (!this->Read(this->ELFHeader)) { | 412 | 2 | this->SetErrorMessage("Failed to read main ELF header."); | 413 | 2 | return; | 414 | 2 | } | 415 | | | 416 | | // Determine the ELF file type. | 417 | 499 | switch (this->ELFHeader.e_type) { | 418 | 1 | case ET_NONE: | 419 | 1 | this->SetErrorMessage("ELF file type is NONE."); | 420 | 1 | return; | 421 | 13 | case ET_REL: | 422 | 13 | this->ELFType = cmELF::FileTypeRelocatableObject; | 423 | 13 | break; | 424 | 208 | case ET_EXEC: | 425 | 208 | this->ELFType = cmELF::FileTypeExecutable; | 426 | 208 | break; | 427 | 168 | case ET_DYN: | 428 | 168 | this->ELFType = cmELF::FileTypeSharedLibrary; | 429 | 168 | break; | 430 | 9 | case ET_CORE: | 431 | 9 | this->ELFType = cmELF::FileTypeCore; | 432 | 9 | break; | 433 | 100 | default: { | 434 | 100 | unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); | 435 | 100 | if (eti >= ET_LOOS && eti <= ET_HIOS) { | 436 | 19 | this->ELFType = cmELF::FileTypeSpecificOS; | 437 | 19 | break; | 438 | 19 | } | 439 | 81 | if (eti >= ET_LOPROC && eti <= ET_HIPROC) { | 440 | 57 | this->ELFType = cmELF::FileTypeSpecificProc; | 441 | 57 | break; | 442 | 57 | } | 443 | 24 | std::ostringstream e; | 444 | 24 | e << "Unknown ELF file type " << eti; | 445 | 24 | this->SetErrorMessage(e.str().c_str()); | 446 | 24 | return; | 447 | 81 | } | 448 | 499 | } | 449 | | | 450 | 474 | this->Machine = this->ELFHeader.e_machine; | 451 | | | 452 | | // Load the section headers. | 453 | 474 | std::size_t const minSections = 1; | 454 | 474 | std::size_t numSections = this->ELFHeader.e_shnum; | 455 | 474 | this->SectionHeaders.resize(std::max(numSections, minSections)); | 456 | 474 | if (!this->LoadSectionHeader(0)) { | 457 | 14 | return; | 458 | 14 | } | 459 | 460 | numSections = this->GetNumberOfSections(); | 460 | 460 | this->SectionHeaders.resize(std::max(numSections, minSections)); | 461 | 2.26M | for (std::size_t i = 1; i < numSections; ++i) { | 462 | 2.26M | if (!this->LoadSectionHeader(i)) { | 463 | 83 | return; | 464 | 83 | } | 465 | 2.26M | } | 466 | 460 | } |
|
467 | | |
468 | | template <class Types> |
469 | | bool cmELFInternalImpl<Types>::LoadDynamicSection() |
470 | 7.16k | { |
471 | | // If there is no dynamic section we are done. |
472 | 7.16k | if (!this->HasDynamicSection()) { |
473 | 217 | return false; |
474 | 217 | } |
475 | | |
476 | | // If the section was already loaded we are done. |
477 | 6.94k | if (!this->DynamicSectionEntries.empty()) { |
478 | 6.12k | return true; |
479 | 6.12k | } |
480 | | |
481 | | // If there are no entries we are done. |
482 | 824 | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; |
483 | 824 | if (sec.sh_entsize == 0) { |
484 | 24 | return false; |
485 | 24 | } |
486 | | |
487 | | // Allocate the dynamic section entries. |
488 | 800 | int n = static_cast<int>(sec.sh_size / sec.sh_entsize); |
489 | 800 | this->DynamicSectionEntries.resize(n); |
490 | | |
491 | | // Read each entry. |
492 | 101k | for (int j = 0; j < n; ++j) { |
493 | | // Seek to the beginning of the section entry. |
494 | 100k | this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j); |
495 | 100k | ELF_Dyn& dyn = this->DynamicSectionEntries[j]; |
496 | | |
497 | | // Try reading the entry. |
498 | 100k | if (!this->Read(dyn)) { |
499 | 87 | this->SetErrorMessage("Error reading entry from DYNAMIC section."); |
500 | 87 | this->DynamicSectionIndex = -1; |
501 | 87 | return false; |
502 | 87 | } |
503 | 100k | } |
504 | 713 | return true; |
505 | 800 | } cmELFInternalImpl<cmELFTypes32>::LoadDynamicSection() Line | Count | Source | 470 | 4.51k | { | 471 | | // If there is no dynamic section we are done. | 472 | 4.51k | if (!this->HasDynamicSection()) { | 473 | 106 | return false; | 474 | 106 | } | 475 | | | 476 | | // If the section was already loaded we are done. | 477 | 4.41k | if (!this->DynamicSectionEntries.empty()) { | 478 | 3.97k | return true; | 479 | 3.97k | } | 480 | | | 481 | | // If there are no entries we are done. | 482 | 437 | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; | 483 | 437 | if (sec.sh_entsize == 0) { | 484 | 12 | return false; | 485 | 12 | } | 486 | | | 487 | | // Allocate the dynamic section entries. | 488 | 425 | int n = static_cast<int>(sec.sh_size / sec.sh_entsize); | 489 | 425 | this->DynamicSectionEntries.resize(n); | 490 | | | 491 | | // Read each entry. | 492 | 91.5k | for (int j = 0; j < n; ++j) { | 493 | | // Seek to the beginning of the section entry. | 494 | 91.2k | this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j); | 495 | 91.2k | ELF_Dyn& dyn = this->DynamicSectionEntries[j]; | 496 | | | 497 | | // Try reading the entry. | 498 | 91.2k | if (!this->Read(dyn)) { | 499 | 45 | this->SetErrorMessage("Error reading entry from DYNAMIC section."); | 500 | 45 | this->DynamicSectionIndex = -1; | 501 | 45 | return false; | 502 | 45 | } | 503 | 91.2k | } | 504 | 380 | return true; | 505 | 425 | } |
cmELFInternalImpl<cmELFTypes64>::LoadDynamicSection() Line | Count | Source | 470 | 2.64k | { | 471 | | // If there is no dynamic section we are done. | 472 | 2.64k | if (!this->HasDynamicSection()) { | 473 | 111 | return false; | 474 | 111 | } | 475 | | | 476 | | // If the section was already loaded we are done. | 477 | 2.53k | if (!this->DynamicSectionEntries.empty()) { | 478 | 2.14k | return true; | 479 | 2.14k | } | 480 | | | 481 | | // If there are no entries we are done. | 482 | 387 | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; | 483 | 387 | if (sec.sh_entsize == 0) { | 484 | 12 | return false; | 485 | 12 | } | 486 | | | 487 | | // Allocate the dynamic section entries. | 488 | 375 | int n = static_cast<int>(sec.sh_size / sec.sh_entsize); | 489 | 375 | this->DynamicSectionEntries.resize(n); | 490 | | | 491 | | // Read each entry. | 492 | 9.89k | for (int j = 0; j < n; ++j) { | 493 | | // Seek to the beginning of the section entry. | 494 | 9.56k | this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j); | 495 | 9.56k | ELF_Dyn& dyn = this->DynamicSectionEntries[j]; | 496 | | | 497 | | // Try reading the entry. | 498 | 9.56k | if (!this->Read(dyn)) { | 499 | 42 | this->SetErrorMessage("Error reading entry from DYNAMIC section."); | 500 | 42 | this->DynamicSectionIndex = -1; | 501 | 42 | return false; | 502 | 42 | } | 503 | 9.56k | } | 504 | 333 | return true; | 505 | 375 | } |
|
506 | | |
507 | | template <class Types> |
508 | | unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j) |
509 | 5.65k | { |
510 | 5.65k | if (!this->LoadDynamicSection()) { |
511 | 0 | return 0; |
512 | 0 | } |
513 | 5.65k | if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) { |
514 | 0 | return 0; |
515 | 0 | } |
516 | 5.65k | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; |
517 | 5.65k | return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j); |
518 | 5.65k | } cmELFInternalImpl<cmELFTypes32>::GetDynamicEntryPosition(int) Line | Count | Source | 509 | 3.75k | { | 510 | 3.75k | if (!this->LoadDynamicSection()) { | 511 | 0 | return 0; | 512 | 0 | } | 513 | 3.75k | if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) { | 514 | 0 | return 0; | 515 | 0 | } | 516 | 3.75k | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; | 517 | 3.75k | return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j); | 518 | 3.75k | } |
cmELFInternalImpl<cmELFTypes64>::GetDynamicEntryPosition(int) Line | Count | Source | 509 | 1.89k | { | 510 | 1.89k | if (!this->LoadDynamicSection()) { | 511 | 0 | return 0; | 512 | 0 | } | 513 | 1.89k | if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) { | 514 | 0 | return 0; | 515 | 0 | } | 516 | 1.89k | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; | 517 | 1.89k | return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j); | 518 | 1.89k | } |
|
519 | | |
520 | | template <class Types> |
521 | | cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries() |
522 | 351 | { |
523 | 351 | cmELF::DynamicEntryList result; |
524 | | |
525 | | // Ensure entries have been read from file |
526 | 351 | if (!this->LoadDynamicSection()) { |
527 | 142 | return result; |
528 | 142 | } |
529 | | |
530 | | // Copy into public array |
531 | 209 | result.reserve(this->DynamicSectionEntries.size()); |
532 | 87.0k | for (ELF_Dyn& dyn : this->DynamicSectionEntries) { |
533 | 87.0k | result.emplace_back(dyn.d_tag, dyn.d_un.d_val); |
534 | 87.0k | } |
535 | | |
536 | 209 | return result; |
537 | 351 | } cmELFInternalImpl<cmELFTypes32>::GetDynamicEntries() Line | Count | Source | 522 | 220 | { | 523 | 220 | cmELF::DynamicEntryList result; | 524 | | | 525 | | // Ensure entries have been read from file | 526 | 220 | if (!this->LoadDynamicSection()) { | 527 | 78 | return result; | 528 | 78 | } | 529 | | | 530 | | // Copy into public array | 531 | 142 | result.reserve(this->DynamicSectionEntries.size()); | 532 | 85.0k | for (ELF_Dyn& dyn : this->DynamicSectionEntries) { | 533 | 85.0k | result.emplace_back(dyn.d_tag, dyn.d_un.d_val); | 534 | 85.0k | } | 535 | | | 536 | 142 | return result; | 537 | 220 | } |
cmELFInternalImpl<cmELFTypes64>::GetDynamicEntries() Line | Count | Source | 522 | 131 | { | 523 | 131 | cmELF::DynamicEntryList result; | 524 | | | 525 | | // Ensure entries have been read from file | 526 | 131 | if (!this->LoadDynamicSection()) { | 527 | 64 | return result; | 528 | 64 | } | 529 | | | 530 | | // Copy into public array | 531 | 67 | result.reserve(this->DynamicSectionEntries.size()); | 532 | 1.96k | for (ELF_Dyn& dyn : this->DynamicSectionEntries) { | 533 | 1.96k | result.emplace_back(dyn.d_tag, dyn.d_un.d_val); | 534 | 1.96k | } | 535 | | | 536 | 67 | return result; | 537 | 131 | } |
|
538 | | |
539 | | template <class Types> |
540 | | std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries( |
541 | | cmELF::DynamicEntryList const& entries) |
542 | 128 | { |
543 | 128 | std::vector<char> result; |
544 | 128 | result.reserve(sizeof(ELF_Dyn) * entries.size()); |
545 | | |
546 | 87.0k | for (auto const& entry : entries) { |
547 | | // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars |
548 | 87.0k | ELF_Dyn dyn; |
549 | 87.0k | dyn.d_tag = static_cast<tagtype>(entry.first); |
550 | 87.0k | dyn.d_un.d_val = static_cast<tagtype>(entry.second); |
551 | | |
552 | 87.0k | if (this->NeedSwap) { |
553 | 17.6k | this->ByteSwap(dyn); |
554 | 17.6k | } |
555 | | |
556 | 87.0k | char* pdyn = reinterpret_cast<char*>(&dyn); |
557 | 87.0k | cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn)); |
558 | 87.0k | } |
559 | | |
560 | 128 | return result; |
561 | 128 | } cmELFInternalImpl<cmELFTypes32>::EncodeDynamicEntries(std::__1::vector<std::__1::pair<long, unsigned long>, std::__1::allocator<std::__1::pair<long, unsigned long> > > const&) Line | Count | Source | 542 | 85 | { | 543 | 85 | std::vector<char> result; | 544 | 85 | result.reserve(sizeof(ELF_Dyn) * entries.size()); | 545 | | | 546 | 85.0k | for (auto const& entry : entries) { | 547 | | // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars | 548 | 85.0k | ELF_Dyn dyn; | 549 | 85.0k | dyn.d_tag = static_cast<tagtype>(entry.first); | 550 | 85.0k | dyn.d_un.d_val = static_cast<tagtype>(entry.second); | 551 | | | 552 | 85.0k | if (this->NeedSwap) { | 553 | 17.6k | this->ByteSwap(dyn); | 554 | 17.6k | } | 555 | | | 556 | 85.0k | char* pdyn = reinterpret_cast<char*>(&dyn); | 557 | 85.0k | cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn)); | 558 | 85.0k | } | 559 | | | 560 | 85 | return result; | 561 | 85 | } |
cmELFInternalImpl<cmELFTypes64>::EncodeDynamicEntries(std::__1::vector<std::__1::pair<long, unsigned long>, std::__1::allocator<std::__1::pair<long, unsigned long> > > const&) Line | Count | Source | 542 | 43 | { | 543 | 43 | std::vector<char> result; | 544 | 43 | result.reserve(sizeof(ELF_Dyn) * entries.size()); | 545 | | | 546 | 1.96k | for (auto const& entry : entries) { | 547 | | // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars | 548 | 1.96k | ELF_Dyn dyn; | 549 | 1.96k | dyn.d_tag = static_cast<tagtype>(entry.first); | 550 | 1.96k | dyn.d_un.d_val = static_cast<tagtype>(entry.second); | 551 | | | 552 | 1.96k | if (this->NeedSwap) { | 553 | 1 | this->ByteSwap(dyn); | 554 | 1 | } | 555 | | | 556 | 1.96k | char* pdyn = reinterpret_cast<char*>(&dyn); | 557 | 1.96k | cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn)); | 558 | 1.96k | } | 559 | | | 560 | 43 | return result; | 561 | 43 | } |
|
562 | | |
563 | | template <class Types> |
564 | | cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( |
565 | | unsigned int tag) |
566 | 1.40k | { |
567 | | // Short-circuit if already checked. |
568 | 1.40k | auto dssi = this->DynamicSectionStrings.find(tag); |
569 | 1.40k | if (dssi != this->DynamicSectionStrings.end()) { |
570 | 247 | if (dssi->second.Position > 0) { |
571 | 35 | return &dssi->second; |
572 | 35 | } |
573 | 212 | return nullptr; |
574 | 247 | } |
575 | | |
576 | | // Create an entry for this tag. Assume it is missing until found. |
577 | 1.15k | StringEntry& se = this->DynamicSectionStrings[tag]; |
578 | 1.15k | se.Position = 0; |
579 | 1.15k | se.Size = 0; |
580 | 1.15k | se.IndexInSection = -1; |
581 | | |
582 | | // Try reading the dynamic section. |
583 | 1.15k | if (!this->LoadDynamicSection()) { |
584 | 186 | return nullptr; |
585 | 186 | } |
586 | | |
587 | | // Get the string table referenced by the DYNAMIC section. |
588 | 972 | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; |
589 | 972 | if (sec.sh_link >= this->SectionHeaders.size()) { |
590 | 158 | this->SetErrorMessage("Section DYNAMIC has invalid string table index."); |
591 | 158 | return nullptr; |
592 | 158 | } |
593 | 814 | ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link]; |
594 | | |
595 | | // Look for the requested entry. |
596 | 814 | for (auto di = this->DynamicSectionEntries.begin(); |
597 | 227k | di != this->DynamicSectionEntries.end(); ++di) { |
598 | 227k | ELF_Dyn& dyn = *di; |
599 | 227k | if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) { |
600 | | // We found the tag requested. |
601 | | // Make sure the position given is within the string section. |
602 | 234 | if (dyn.d_un.d_val >= strtab.sh_size) { |
603 | 116 | this->SetErrorMessage("Section DYNAMIC references string beyond " |
604 | 116 | "the end of its string section."); |
605 | 116 | return nullptr; |
606 | 116 | } |
607 | | |
608 | | // Seek to the position reported by the entry. |
609 | 118 | unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val); |
610 | 118 | unsigned long last = first; |
611 | 118 | unsigned long end = static_cast<unsigned long>(strtab.sh_size); |
612 | 118 | this->Stream->seekg(strtab.sh_offset + first); |
613 | | |
614 | | // Read the string. It may be followed by more than one NULL |
615 | | // terminator. Count the total size of the region allocated to |
616 | | // the string. This assumes that the next string in the table |
617 | | // is non-empty, but the "chrpath" tool makes the same |
618 | | // assumption. |
619 | 118 | bool terminated = false; |
620 | 118 | char c; |
621 | 1.65k | while (last != end && this->Stream->get(c) && !(terminated && c)) { |
622 | 1.53k | ++last; |
623 | 1.53k | if (c) { |
624 | 844 | se.Value += c; |
625 | 844 | } else { |
626 | 690 | terminated = true; |
627 | 690 | } |
628 | 1.53k | } |
629 | | |
630 | | // Make sure the whole value was read. |
631 | 118 | if (!(*this->Stream)) { |
632 | 44 | if (tag == cmELF::TagRPath) { |
633 | 7 | this->SetErrorMessage( |
634 | 7 | "Dynamic section specifies unreadable DT_RPATH"); |
635 | 37 | } else if (tag == cmELF::TagRunPath) { |
636 | 14 | this->SetErrorMessage( |
637 | 14 | "Dynamic section specifies unreadable DT_RUNPATH"); |
638 | 23 | } else if (tag == cmELF::TagMipsRldMapRel) { |
639 | 0 | this->SetErrorMessage( |
640 | 0 | "Dynamic section specifies unreadable DT_MIPS_RLD_MAP_REL"); |
641 | 23 | } else { |
642 | 23 | this->SetErrorMessage("Dynamic section specifies unreadable value" |
643 | 23 | " for unexpected attribute"); |
644 | 23 | } |
645 | 44 | se.Value = ""; |
646 | 44 | return nullptr; |
647 | 44 | } |
648 | | |
649 | | // The value has been read successfully. Report it. |
650 | 74 | se.Position = static_cast<unsigned long>(strtab.sh_offset + first); |
651 | 74 | se.Size = last - first; |
652 | 74 | se.IndexInSection = |
653 | 74 | static_cast<int>(di - this->DynamicSectionEntries.begin()); |
654 | 74 | return &se; |
655 | 118 | } |
656 | 227k | } |
657 | 580 | return nullptr; |
658 | 814 | } cmELFInternalImpl<cmELFTypes32>::GetDynamicSectionString(unsigned int) Line | Count | Source | 566 | 671 | { | 567 | | // Short-circuit if already checked. | 568 | 671 | auto dssi = this->DynamicSectionStrings.find(tag); | 569 | 671 | if (dssi != this->DynamicSectionStrings.end()) { | 570 | 128 | if (dssi->second.Position > 0) { | 571 | 32 | return &dssi->second; | 572 | 32 | } | 573 | 96 | return nullptr; | 574 | 128 | } | 575 | | | 576 | | // Create an entry for this tag. Assume it is missing until found. | 577 | 543 | StringEntry& se = this->DynamicSectionStrings[tag]; | 578 | 543 | se.Position = 0; | 579 | 543 | se.Size = 0; | 580 | 543 | se.IndexInSection = -1; | 581 | | | 582 | | // Try reading the dynamic section. | 583 | 543 | if (!this->LoadDynamicSection()) { | 584 | 85 | return nullptr; | 585 | 85 | } | 586 | | | 587 | | // Get the string table referenced by the DYNAMIC section. | 588 | 458 | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; | 589 | 458 | if (sec.sh_link >= this->SectionHeaders.size()) { | 590 | 60 | this->SetErrorMessage("Section DYNAMIC has invalid string table index."); | 591 | 60 | return nullptr; | 592 | 60 | } | 593 | 398 | ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link]; | 594 | | | 595 | | // Look for the requested entry. | 596 | 398 | for (auto di = this->DynamicSectionEntries.begin(); | 597 | 206k | di != this->DynamicSectionEntries.end(); ++di) { | 598 | 206k | ELF_Dyn& dyn = *di; | 599 | 206k | if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) { | 600 | | // We found the tag requested. | 601 | | // Make sure the position given is within the string section. | 602 | 104 | if (dyn.d_un.d_val >= strtab.sh_size) { | 603 | 26 | this->SetErrorMessage("Section DYNAMIC references string beyond " | 604 | 26 | "the end of its string section."); | 605 | 26 | return nullptr; | 606 | 26 | } | 607 | | | 608 | | // Seek to the position reported by the entry. | 609 | 78 | unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val); | 610 | 78 | unsigned long last = first; | 611 | 78 | unsigned long end = static_cast<unsigned long>(strtab.sh_size); | 612 | 78 | this->Stream->seekg(strtab.sh_offset + first); | 613 | | | 614 | | // Read the string. It may be followed by more than one NULL | 615 | | // terminator. Count the total size of the region allocated to | 616 | | // the string. This assumes that the next string in the table | 617 | | // is non-empty, but the "chrpath" tool makes the same | 618 | | // assumption. | 619 | 78 | bool terminated = false; | 620 | 78 | char c; | 621 | 1.04k | while (last != end && this->Stream->get(c) && !(terminated && c)) { | 622 | 970 | ++last; | 623 | 970 | if (c) { | 624 | 573 | se.Value += c; | 625 | 573 | } else { | 626 | 397 | terminated = true; | 627 | 397 | } | 628 | 970 | } | 629 | | | 630 | | // Make sure the whole value was read. | 631 | 78 | if (!(*this->Stream)) { | 632 | 25 | if (tag == cmELF::TagRPath) { | 633 | 3 | this->SetErrorMessage( | 634 | 3 | "Dynamic section specifies unreadable DT_RPATH"); | 635 | 22 | } else if (tag == cmELF::TagRunPath) { | 636 | 1 | this->SetErrorMessage( | 637 | 1 | "Dynamic section specifies unreadable DT_RUNPATH"); | 638 | 21 | } else if (tag == cmELF::TagMipsRldMapRel) { | 639 | 0 | this->SetErrorMessage( | 640 | 0 | "Dynamic section specifies unreadable DT_MIPS_RLD_MAP_REL"); | 641 | 21 | } else { | 642 | 21 | this->SetErrorMessage("Dynamic section specifies unreadable value" | 643 | 21 | " for unexpected attribute"); | 644 | 21 | } | 645 | 25 | se.Value = ""; | 646 | 25 | return nullptr; | 647 | 25 | } | 648 | | | 649 | | // The value has been read successfully. Report it. | 650 | 53 | se.Position = static_cast<unsigned long>(strtab.sh_offset + first); | 651 | 53 | se.Size = last - first; | 652 | 53 | se.IndexInSection = | 653 | 53 | static_cast<int>(di - this->DynamicSectionEntries.begin()); | 654 | 53 | return &se; | 655 | 78 | } | 656 | 206k | } | 657 | 294 | return nullptr; | 658 | 398 | } |
cmELFInternalImpl<cmELFTypes64>::GetDynamicSectionString(unsigned int) Line | Count | Source | 566 | 734 | { | 567 | | // Short-circuit if already checked. | 568 | 734 | auto dssi = this->DynamicSectionStrings.find(tag); | 569 | 734 | if (dssi != this->DynamicSectionStrings.end()) { | 570 | 119 | if (dssi->second.Position > 0) { | 571 | 3 | return &dssi->second; | 572 | 3 | } | 573 | 116 | return nullptr; | 574 | 119 | } | 575 | | | 576 | | // Create an entry for this tag. Assume it is missing until found. | 577 | 615 | StringEntry& se = this->DynamicSectionStrings[tag]; | 578 | 615 | se.Position = 0; | 579 | 615 | se.Size = 0; | 580 | 615 | se.IndexInSection = -1; | 581 | | | 582 | | // Try reading the dynamic section. | 583 | 615 | if (!this->LoadDynamicSection()) { | 584 | 101 | return nullptr; | 585 | 101 | } | 586 | | | 587 | | // Get the string table referenced by the DYNAMIC section. | 588 | 514 | ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; | 589 | 514 | if (sec.sh_link >= this->SectionHeaders.size()) { | 590 | 98 | this->SetErrorMessage("Section DYNAMIC has invalid string table index."); | 591 | 98 | return nullptr; | 592 | 98 | } | 593 | 416 | ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link]; | 594 | | | 595 | | // Look for the requested entry. | 596 | 416 | for (auto di = this->DynamicSectionEntries.begin(); | 597 | 21.1k | di != this->DynamicSectionEntries.end(); ++di) { | 598 | 20.8k | ELF_Dyn& dyn = *di; | 599 | 20.8k | if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) { | 600 | | // We found the tag requested. | 601 | | // Make sure the position given is within the string section. | 602 | 130 | if (dyn.d_un.d_val >= strtab.sh_size) { | 603 | 90 | this->SetErrorMessage("Section DYNAMIC references string beyond " | 604 | 90 | "the end of its string section."); | 605 | 90 | return nullptr; | 606 | 90 | } | 607 | | | 608 | | // Seek to the position reported by the entry. | 609 | 40 | unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val); | 610 | 40 | unsigned long last = first; | 611 | 40 | unsigned long end = static_cast<unsigned long>(strtab.sh_size); | 612 | 40 | this->Stream->seekg(strtab.sh_offset + first); | 613 | | | 614 | | // Read the string. It may be followed by more than one NULL | 615 | | // terminator. Count the total size of the region allocated to | 616 | | // the string. This assumes that the next string in the table | 617 | | // is non-empty, but the "chrpath" tool makes the same | 618 | | // assumption. | 619 | 40 | bool terminated = false; | 620 | 40 | char c; | 621 | 604 | while (last != end && this->Stream->get(c) && !(terminated && c)) { | 622 | 564 | ++last; | 623 | 564 | if (c) { | 624 | 271 | se.Value += c; | 625 | 293 | } else { | 626 | 293 | terminated = true; | 627 | 293 | } | 628 | 564 | } | 629 | | | 630 | | // Make sure the whole value was read. | 631 | 40 | if (!(*this->Stream)) { | 632 | 19 | if (tag == cmELF::TagRPath) { | 633 | 4 | this->SetErrorMessage( | 634 | 4 | "Dynamic section specifies unreadable DT_RPATH"); | 635 | 15 | } else if (tag == cmELF::TagRunPath) { | 636 | 13 | this->SetErrorMessage( | 637 | 13 | "Dynamic section specifies unreadable DT_RUNPATH"); | 638 | 13 | } else if (tag == cmELF::TagMipsRldMapRel) { | 639 | 0 | this->SetErrorMessage( | 640 | 0 | "Dynamic section specifies unreadable DT_MIPS_RLD_MAP_REL"); | 641 | 2 | } else { | 642 | 2 | this->SetErrorMessage("Dynamic section specifies unreadable value" | 643 | 2 | " for unexpected attribute"); | 644 | 2 | } | 645 | 19 | se.Value = ""; | 646 | 19 | return nullptr; | 647 | 19 | } | 648 | | | 649 | | // The value has been read successfully. Report it. | 650 | 21 | se.Position = static_cast<unsigned long>(strtab.sh_offset + first); | 651 | 21 | se.Size = last - first; | 652 | 21 | se.IndexInSection = | 653 | 21 | static_cast<int>(di - this->DynamicSectionEntries.begin()); | 654 | 21 | return &se; | 655 | 40 | } | 656 | 20.8k | } | 657 | 286 | return nullptr; | 658 | 416 | } |
|
659 | | |
660 | | //============================================================================ |
661 | | // External class implementation. |
662 | | |
663 | | long const cmELF::TagRPath = DT_RPATH; |
664 | | long const cmELF::TagRunPath = DT_RUNPATH; |
665 | | long const cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL; |
666 | | |
667 | | cmELF::cmELF(char const* fname) |
668 | 1.10k | { |
669 | | // Try to open the file. |
670 | 1.10k | auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary); |
671 | | |
672 | | // Quit now if the file could not be opened. |
673 | 1.10k | if (!fin || !*fin) { |
674 | 0 | this->ErrorMessage = "Error opening input file."; |
675 | 0 | return; |
676 | 0 | } |
677 | | |
678 | | // Read the ELF identification block. |
679 | 1.10k | char ident[EI_NIDENT]; |
680 | 1.10k | if (!fin->read(ident, EI_NIDENT)) { |
681 | 0 | this->ErrorMessage = "Error reading ELF identification."; |
682 | 0 | return; |
683 | 0 | } |
684 | 1.10k | if (!fin->seekg(0)) { |
685 | 0 | this->ErrorMessage = "Error seeking to beginning of file."; |
686 | 0 | return; |
687 | 0 | } |
688 | | |
689 | | // Verify the ELF identification. |
690 | 1.10k | if (!(ident[EI_MAG0] == ELFMAG0 && ident[EI_MAG1] == ELFMAG1 && |
691 | 1.05k | ident[EI_MAG2] == ELFMAG2 && ident[EI_MAG3] == ELFMAG3)) { |
692 | 73 | this->ErrorMessage = "File does not have a valid ELF identification."; |
693 | 73 | return; |
694 | 73 | } |
695 | | |
696 | | // Check the byte order in which the rest of the file is encoded. |
697 | 1.02k | cmELFInternal::ByteOrderType order; |
698 | 1.02k | if (ident[EI_DATA] == ELFDATA2LSB) { |
699 | | // File is LSB. |
700 | 769 | order = cmELFInternal::ByteOrderLSB; |
701 | 769 | } else if (ident[EI_DATA] == ELFDATA2MSB) { |
702 | | // File is MSB. |
703 | 247 | order = cmELFInternal::ByteOrderMSB; |
704 | 247 | } else { |
705 | 12 | this->ErrorMessage = "ELF file is not LSB or MSB encoded."; |
706 | 12 | return; |
707 | 12 | } |
708 | | |
709 | | // Check the class of the file and construct the corresponding |
710 | | // parser implementation. |
711 | 1.01k | if (ident[EI_CLASS] == ELFCLASS32) { |
712 | | // 32-bit ELF |
713 | 505 | this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>( |
714 | 505 | this, std::move(fin), order); |
715 | 511 | } else if (ident[EI_CLASS] == ELFCLASS64) { |
716 | | // 64-bit ELF |
717 | 501 | this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>( |
718 | 501 | this, std::move(fin), order); |
719 | 501 | } else { |
720 | 10 | this->ErrorMessage = "ELF file class is not 32-bit or 64-bit."; |
721 | 10 | return; |
722 | 10 | } |
723 | 1.01k | } |
724 | | |
725 | 1.10k | cmELF::~cmELF() = default; |
726 | | |
727 | | bool cmELF::Valid() const |
728 | 14.9k | { |
729 | 14.9k | return this->Internal && this->Internal->GetFileType() != FileTypeInvalid; |
730 | 14.9k | } |
731 | | |
732 | | cmELF::FileType cmELF::GetFileType() const |
733 | 732 | { |
734 | 732 | if (this->Valid()) { |
735 | 732 | return this->Internal->GetFileType(); |
736 | 732 | } |
737 | 0 | return FileTypeInvalid; |
738 | 732 | } |
739 | | |
740 | | std::uint16_t cmELF::GetMachine() const |
741 | 732 | { |
742 | 732 | if (this->Valid()) { |
743 | 732 | return this->Internal->GetMachine(); |
744 | 732 | } |
745 | 0 | return 0; |
746 | 732 | } |
747 | | |
748 | | std::size_t cmELF::GetNumberOfSections() const |
749 | 732 | { |
750 | 732 | if (this->Valid()) { |
751 | 732 | return this->Internal->GetNumberOfSections(); |
752 | 732 | } |
753 | 0 | return 0; |
754 | 732 | } |
755 | | |
756 | | unsigned long cmELF::GetDynamicEntryPosition(int index) const |
757 | 5.65k | { |
758 | 5.65k | if (this->Valid()) { |
759 | 5.65k | return this->Internal->GetDynamicEntryPosition(index); |
760 | 5.65k | } |
761 | 0 | return 0; |
762 | 5.65k | } |
763 | | |
764 | | cmELF::DynamicEntryList cmELF::GetDynamicEntries() const |
765 | 732 | { |
766 | 732 | if (this->Valid()) { |
767 | 351 | return this->Internal->GetDynamicEntries(); |
768 | 351 | } |
769 | | |
770 | 381 | return cmELF::DynamicEntryList(); |
771 | 732 | } |
772 | | |
773 | | std::vector<char> cmELF::EncodeDynamicEntries( |
774 | | cmELF::DynamicEntryList const& dentries) const |
775 | 128 | { |
776 | 128 | if (this->Valid()) { |
777 | 128 | return this->Internal->EncodeDynamicEntries(dentries); |
778 | 128 | } |
779 | | |
780 | 0 | return std::vector<char>(); |
781 | 128 | } |
782 | | |
783 | | bool cmELF::HasDynamicSection() const |
784 | 732 | { |
785 | 732 | return this->Valid() && this->Internal->HasDynamicSection(); |
786 | 732 | } |
787 | | |
788 | | bool cmELF::GetSOName(std::string& soname) |
789 | 732 | { |
790 | 732 | if (StringEntry const* se = this->GetSOName()) { |
791 | 38 | soname = se->Value; |
792 | 38 | return true; |
793 | 38 | } |
794 | 694 | return false; |
795 | 732 | } |
796 | | |
797 | | cmELF::StringEntry const* cmELF::GetSOName() |
798 | 1.46k | { |
799 | 1.46k | if (this->Valid() && |
800 | 1.30k | this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) { |
801 | 649 | return this->Internal->GetSOName(); |
802 | 649 | } |
803 | 815 | return nullptr; |
804 | 1.46k | } |
805 | | |
806 | | cmELF::StringEntry const* cmELF::GetRPath() |
807 | 732 | { |
808 | 732 | if (this->Valid() && |
809 | 577 | (this->Internal->GetFileType() == cmELF::FileTypeExecutable || |
810 | 454 | this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) { |
811 | 454 | return this->Internal->GetRPath(); |
812 | 454 | } |
813 | 278 | return nullptr; |
814 | 732 | } |
815 | | |
816 | | cmELF::StringEntry const* cmELF::GetRunPath() |
817 | 732 | { |
818 | 732 | if (this->Valid() && |
819 | 425 | (this->Internal->GetFileType() == cmELF::FileTypeExecutable || |
820 | 346 | this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) { |
821 | 302 | return this->Internal->GetRunPath(); |
822 | 302 | } |
823 | 430 | return nullptr; |
824 | 732 | } |
825 | | |
826 | | bool cmELF::IsMIPS() const |
827 | 732 | { |
828 | 732 | if (this->Valid()) { |
829 | 732 | return this->Internal->IsMips(); |
830 | 732 | } |
831 | 0 | return false; |
832 | 732 | } |
833 | | |
834 | | void cmELF::PrintInfo(std::ostream& os) const |
835 | 732 | { |
836 | 732 | if (this->Valid()) { |
837 | 327 | this->Internal->PrintInfo(os); |
838 | 405 | } else { |
839 | 405 | os << "Not a valid ELF file.\n"; |
840 | 405 | } |
841 | 732 | } |