Coverage Report

Created: 2026-07-30 06:52

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