Coverage Report

Created: 2026-07-14 07:09

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.62k
{
37
3.62k
  char one_byte;
38
3.62k
  one_byte = data[0];
39
3.62k
  data[0] = data[1];
40
3.62k
  data[1] = one_byte;
41
3.62k
}
42
static void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
43
39.2M
{
44
39.2M
  char one_byte;
45
39.2M
  one_byte = data[0];
46
39.2M
  data[0] = data[3];
47
39.2M
  data[3] = one_byte;
48
39.2M
  one_byte = data[1];
49
39.2M
  data[1] = data[2];
50
39.2M
  data[2] = one_byte;
51
39.2M
}
52
static void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/)
53
39.4M
{
54
39.4M
  char one_byte;
55
39.4M
  one_byte = data[0];
56
39.4M
  data[0] = data[7];
57
39.4M
  data[7] = one_byte;
58
39.4M
  one_byte = data[1];
59
39.4M
  data[1] = data[6];
60
39.4M
  data[6] = one_byte;
61
39.4M
  one_byte = data[2];
62
39.4M
  data[2] = data[5];
63
39.4M
  data[5] = one_byte;
64
39.4M
  one_byte = data[3];
65
39.4M
  data[3] = data[4];
66
39.4M
  data[4] = one_byte;
67
39.4M
}
68
69
// Low-level byte swapping interface.
70
template <typename T>
71
void cmELFByteSwap(T& x)
72
78.6M
{
73
78.6M
  cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
74
78.6M
}
void cmELFByteSwap<unsigned short>(unsigned short&)
Line
Count
Source
72
3.62k
{
73
3.62k
  cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
74
3.62k
}
void cmELFByteSwap<unsigned int>(unsigned int&)
Line
Count
Source
72
39.0M
{
73
39.0M
  cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
74
39.0M
}
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
39.4M
{
73
39.4M
  cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
74
39.4M
}
void cmELFByteSwap<long>(long&)
Line
Count
Source
72
1.86k
{
73
1.86k
  cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
74
1.86k
}
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.17k
    : External(external)
90
1.17k
    , Stream(std::move(fin))
91
1.17k
    , ByteOrder(order)
92
1.17k
  {
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.17k
#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
97
1.17k
    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.17k
    this->DynamicSectionIndex = -1;
106
1.17k
  }
107
108
  // Destruct and delete the file stream object.
109
1.17k
  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.0k
  bool HasDynamicSection() const { return this->DynamicSectionIndex >= 0; }
123
124
  // Lookup the SONAME in the DYNAMIC section.
125
  StringEntry const* GetSOName()
126
687
  {
127
687
    return this->GetDynamicSectionString(DT_SONAME);
128
687
  }
129
130
  // Lookup the RPATH in the DYNAMIC section.
131
  StringEntry const* GetRPath()
132
621
  {
133
621
    return this->GetDynamicSectionString(DT_RPATH);
134
621
  }
135
136
  // Lookup the RUNPATH in the DYNAMIC section.
137
  StringEntry const* GetRunPath()
138
339
  {
139
339
    return this->GetDynamicSectionString(DT_RUNPATH);
140
339
  }
141
142
  // Return the recorded ELF type.
143
26.0k
  cmELF::FileType GetFileType() const { return this->ELFType; }
144
145
  // Return the recorded machine.
146
950
  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
714
  {
175
714
    this->External->ErrorMessage = msg;
176
714
    this->ELFType = cmELF::FileTypeInvalid;
177
714
  }
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
197
  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
265
  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
2.04k
  {
224
2.04k
    std::size_t count = this->ELFHeader.e_shnum;
225
2.04k
    if (!this->SectionHeaders.empty()) {
226
2.04k
      count += static_cast<std::size_t>(this->SectionHeaders[0].sh_size);
227
2.04k
    }
228
    // Prevent OOM from malformed files.
229
2.04k
    if (count > kMaxSections) {
230
676
      return kMaxSections;
231
676
    }
232
1.36k
    return count;
233
2.04k
  }
cmELFInternalImpl<cmELFTypes32>::GetNumberOfSections() const
Line
Count
Source
223
787
  {
224
787
    std::size_t count = this->ELFHeader.e_shnum;
225
787
    if (!this->SectionHeaders.empty()) {
226
787
      count += static_cast<std::size_t>(this->SectionHeaders[0].sh_size);
227
787
    }
228
    // Prevent OOM from malformed files.
229
787
    if (count > kMaxSections) {
230
290
      return kMaxSections;
231
290
    }
232
497
    return count;
233
787
  }
cmELFInternalImpl<cmELFTypes64>::GetNumberOfSections() const
Line
Count
Source
223
1.25k
  {
224
1.25k
    std::size_t count = this->ELFHeader.e_shnum;
225
1.25k
    if (!this->SectionHeaders.empty()) {
226
1.25k
      count += static_cast<std::size_t>(this->SectionHeaders[0].sh_size);
227
1.25k
    }
228
    // Prevent OOM from malformed files.
229
1.25k
    if (count > kMaxSections) {
230
386
      return kMaxSections;
231
386
    }
232
872
    return count;
233
1.25k
  }
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
950
  bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; }
cmELFInternalImpl<cmELFTypes32>::IsMips() const
Line
Count
Source
245
373
  bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; }
cmELFInternalImpl<cmELFTypes64>::IsMips() const
Line
Count
Source
245
577
  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
462
  {
250
462
    os << "ELF " << Types::GetName();
251
462
    if (this->ByteOrder == ByteOrderMSB) {
252
73
      os << " MSB";
253
389
    } else if (this->ByteOrder == ByteOrderLSB) {
254
389
      os << " LSB";
255
389
    }
256
462
    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
152
      case cmELF::FileTypeExecutable:
264
152
        os << " executable";
265
152
        break;
266
163
      case cmELF::FileTypeSharedLibrary:
267
163
        os << " shared library";
268
163
        break;
269
21
      case cmELF::FileTypeCore:
270
21
        os << " core file";
271
21
        break;
272
22
      case cmELF::FileTypeSpecificOS:
273
22
        os << " os-specific type";
274
22
        break;
275
78
      case cmELF::FileTypeSpecificProc:
276
78
        os << " processor-specific type";
277
78
        break;
278
462
    }
279
462
    os << "\n";
280
462
  }
cmELFInternalImpl<cmELFTypes32>::PrintInfo(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
249
197
  {
250
197
    os << "ELF " << Types::GetName();
251
197
    if (this->ByteOrder == ByteOrderMSB) {
252
23
      os << " MSB";
253
174
    } else if (this->ByteOrder == ByteOrderLSB) {
254
174
      os << " LSB";
255
174
    }
256
197
    switch (this->ELFType) {
257
0
      case cmELF::FileTypeInvalid:
258
0
        os << " invalid file";
259
0
        break;
260
7
      case cmELF::FileTypeRelocatableObject:
261
7
        os << " relocatable object";
262
7
        break;
263
60
      case cmELF::FileTypeExecutable:
264
60
        os << " executable";
265
60
        break;
266
79
      case cmELF::FileTypeSharedLibrary:
267
79
        os << " shared library";
268
79
        break;
269
16
      case cmELF::FileTypeCore:
270
16
        os << " core file";
271
16
        break;
272
7
      case cmELF::FileTypeSpecificOS:
273
7
        os << " os-specific type";
274
7
        break;
275
28
      case cmELF::FileTypeSpecificProc:
276
28
        os << " processor-specific type";
277
28
        break;
278
197
    }
279
197
    os << "\n";
280
197
  }
cmELFInternalImpl<cmELFTypes64>::PrintInfo(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
249
265
  {
250
265
    os << "ELF " << Types::GetName();
251
265
    if (this->ByteOrder == ByteOrderMSB) {
252
50
      os << " MSB";
253
215
    } else if (this->ByteOrder == ByteOrderLSB) {
254
215
      os << " LSB";
255
215
    }
256
265
    switch (this->ELFType) {
257
0
      case cmELF::FileTypeInvalid:
258
0
        os << " invalid file";
259
0
        break;
260
19
      case cmELF::FileTypeRelocatableObject:
261
19
        os << " relocatable object";
262
19
        break;
263
92
      case cmELF::FileTypeExecutable:
264
92
        os << " executable";
265
92
        break;
266
84
      case cmELF::FileTypeSharedLibrary:
267
84
        os << " shared library";
268
84
        break;
269
5
      case cmELF::FileTypeCore:
270
5
        os << " core file";
271
5
        break;
272
15
      case cmELF::FileTypeSpecificOS:
273
15
        os << " os-specific type";
274
15
        break;
275
50
      case cmELF::FileTypeSpecificProc:
276
50
        os << " processor-specific type";
277
50
        break;
278
265
    }
279
265
    os << "\n";
280
265
  }
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
360
  {
288
360
    cmELFByteSwap(elf_header.e_type);
289
360
    cmELFByteSwap(elf_header.e_machine);
290
360
    cmELFByteSwap(elf_header.e_version);
291
360
    cmELFByteSwap(elf_header.e_entry);
292
360
    cmELFByteSwap(elf_header.e_phoff);
293
360
    cmELFByteSwap(elf_header.e_shoff);
294
360
    cmELFByteSwap(elf_header.e_flags);
295
360
    cmELFByteSwap(elf_header.e_ehsize);
296
360
    cmELFByteSwap(elf_header.e_phentsize);
297
360
    cmELFByteSwap(elf_header.e_phnum);
298
360
    cmELFByteSwap(elf_header.e_shentsize);
299
360
    cmELFByteSwap(elf_header.e_shnum);
300
360
    cmELFByteSwap(elf_header.e_shstrndx);
301
360
  }
cmELFInternalImpl<cmELFTypes32>::ByteSwap(Elf32_Ehdr&)
Line
Count
Source
287
99
  {
288
99
    cmELFByteSwap(elf_header.e_type);
289
99
    cmELFByteSwap(elf_header.e_machine);
290
99
    cmELFByteSwap(elf_header.e_version);
291
99
    cmELFByteSwap(elf_header.e_entry);
292
99
    cmELFByteSwap(elf_header.e_phoff);
293
99
    cmELFByteSwap(elf_header.e_shoff);
294
99
    cmELFByteSwap(elf_header.e_flags);
295
99
    cmELFByteSwap(elf_header.e_ehsize);
296
99
    cmELFByteSwap(elf_header.e_phentsize);
297
99
    cmELFByteSwap(elf_header.e_phnum);
298
99
    cmELFByteSwap(elf_header.e_shentsize);
299
99
    cmELFByteSwap(elf_header.e_shnum);
300
99
    cmELFByteSwap(elf_header.e_shstrndx);
301
99
  }
cmELFInternalImpl<cmELFTypes64>::ByteSwap(Elf64_Ehdr&)
Line
Count
Source
287
261
  {
288
261
    cmELFByteSwap(elf_header.e_type);
289
261
    cmELFByteSwap(elf_header.e_machine);
290
261
    cmELFByteSwap(elf_header.e_version);
291
261
    cmELFByteSwap(elf_header.e_entry);
292
261
    cmELFByteSwap(elf_header.e_phoff);
293
261
    cmELFByteSwap(elf_header.e_shoff);
294
261
    cmELFByteSwap(elf_header.e_flags);
295
261
    cmELFByteSwap(elf_header.e_ehsize);
296
261
    cmELFByteSwap(elf_header.e_phentsize);
297
261
    cmELFByteSwap(elf_header.e_phnum);
298
261
    cmELFByteSwap(elf_header.e_shentsize);
299
261
    cmELFByteSwap(elf_header.e_shnum);
300
261
    cmELFByteSwap(elf_header.e_shstrndx);
301
261
  }
302
303
  void ByteSwap(ELF_Shdr& sec_header)
304
7.83M
  {
305
7.83M
    cmELFByteSwap(sec_header.sh_name);
306
7.83M
    cmELFByteSwap(sec_header.sh_type);
307
7.83M
    cmELFByteSwap(sec_header.sh_flags);
308
7.83M
    cmELFByteSwap(sec_header.sh_addr);
309
7.83M
    cmELFByteSwap(sec_header.sh_offset);
310
7.83M
    cmELFByteSwap(sec_header.sh_size);
311
7.83M
    cmELFByteSwap(sec_header.sh_link);
312
7.83M
    cmELFByteSwap(sec_header.sh_info);
313
7.83M
    cmELFByteSwap(sec_header.sh_addralign);
314
7.83M
    cmELFByteSwap(sec_header.sh_entsize);
315
7.83M
  }
cmELFInternalImpl<cmELFTypes32>::ByteSwap(Elf32_Shdr&)
Line
Count
Source
304
1.25M
  {
305
1.25M
    cmELFByteSwap(sec_header.sh_name);
306
1.25M
    cmELFByteSwap(sec_header.sh_type);
307
1.25M
    cmELFByteSwap(sec_header.sh_flags);
308
1.25M
    cmELFByteSwap(sec_header.sh_addr);
309
1.25M
    cmELFByteSwap(sec_header.sh_offset);
310
1.25M
    cmELFByteSwap(sec_header.sh_size);
311
1.25M
    cmELFByteSwap(sec_header.sh_link);
312
1.25M
    cmELFByteSwap(sec_header.sh_info);
313
1.25M
    cmELFByteSwap(sec_header.sh_addralign);
314
1.25M
    cmELFByteSwap(sec_header.sh_entsize);
315
1.25M
  }
cmELFInternalImpl<cmELFTypes64>::ByteSwap(Elf64_Shdr&)
Line
Count
Source
304
6.57M
  {
305
6.57M
    cmELFByteSwap(sec_header.sh_name);
306
6.57M
    cmELFByteSwap(sec_header.sh_type);
307
6.57M
    cmELFByteSwap(sec_header.sh_flags);
308
6.57M
    cmELFByteSwap(sec_header.sh_addr);
309
6.57M
    cmELFByteSwap(sec_header.sh_offset);
310
6.57M
    cmELFByteSwap(sec_header.sh_size);
311
6.57M
    cmELFByteSwap(sec_header.sh_link);
312
6.57M
    cmELFByteSwap(sec_header.sh_info);
313
6.57M
    cmELFByteSwap(sec_header.sh_addralign);
314
6.57M
    cmELFByteSwap(sec_header.sh_entsize);
315
6.57M
  }
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
1.86k
  {
319
1.86k
    cmELFByteSwap(dyn.d_tag);
320
1.86k
    cmELFByteSwap(dyn.d_un.d_val);
321
1.86k
  }
322
323
  bool FileTypeValid(ELF_Half et)
324
1.67k
  {
325
1.67k
    unsigned int eti = static_cast<unsigned int>(et);
326
1.67k
    if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN ||
327
878
        eti == ET_CORE) {
328
878
      return true;
329
878
    }
330
796
    if (eti >= ET_LOOS && eti <= ET_HIOS) {
331
51
      return true;
332
51
    }
333
745
    if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
334
190
      return true;
335
190
    }
336
555
    return false;
337
745
  }
cmELFInternalImpl<cmELFTypes32>::FileTypeValid(unsigned short)
Line
Count
Source
324
534
  {
325
534
    unsigned int eti = static_cast<unsigned int>(et);
326
534
    if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN ||
327
339
        eti == ET_CORE) {
328
339
      return true;
329
339
    }
330
195
    if (eti >= ET_LOOS && eti <= ET_HIOS) {
331
23
      return true;
332
23
    }
333
172
    if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
334
66
      return true;
335
66
    }
336
106
    return false;
337
172
  }
cmELFInternalImpl<cmELFTypes64>::FileTypeValid(unsigned short)
Line
Count
Source
324
1.14k
  {
325
1.14k
    unsigned int eti = static_cast<unsigned int>(et);
326
1.14k
    if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN ||
327
616
        eti == ET_CORE) {
328
539
      return true;
329
539
    }
330
601
    if (eti >= ET_LOOS && eti <= ET_HIOS) {
331
28
      return true;
332
28
    }
333
573
    if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
334
124
      return true;
335
124
    }
336
449
    return false;
337
573
  }
338
339
  bool Read(ELF_Ehdr& x)
340
1.17k
  {
341
    // Read the header from the file.
342
1.17k
    if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) {
343
7
      return false;
344
7
    }
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.16k
    ELF_Half et = x.e_type;
353
1.16k
    if (this->NeedSwap) {
354
237
      cmELFByteSwap(et);
355
237
    }
356
1.16k
    if (!this->FileTypeValid(et)) {
357
505
      cmELFByteSwap(et);
358
505
      if (this->FileTypeValid(et)) {
359
        // The previous byte order guess was wrong.  Flip it.
360
455
        this->NeedSwap = !this->NeedSwap;
361
455
      }
362
505
    }
363
364
    // Fix the byte order of the header.
365
1.16k
    if (this->NeedSwap) {
366
360
      this->ByteSwap(x);
367
360
    }
368
1.16k
    return true;
369
1.17k
  }
cmELFInternalImpl<cmELFTypes32>::Read(Elf32_Ehdr&)
Line
Count
Source
340
451
  {
341
    // Read the header from the file.
342
451
    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
448
    ELF_Half et = x.e_type;
353
448
    if (this->NeedSwap) {
354
53
      cmELFByteSwap(et);
355
53
    }
356
448
    if (!this->FileTypeValid(et)) {
357
86
      cmELFByteSwap(et);
358
86
      if (this->FileTypeValid(et)) {
359
        // The previous byte order guess was wrong.  Flip it.
360
66
        this->NeedSwap = !this->NeedSwap;
361
66
      }
362
86
    }
363
364
    // Fix the byte order of the header.
365
448
    if (this->NeedSwap) {
366
99
      this->ByteSwap(x);
367
99
    }
368
448
    return true;
369
451
  }
cmELFInternalImpl<cmELFTypes64>::Read(Elf64_Ehdr&)
Line
Count
Source
340
725
  {
341
    // Read the header from the file.
342
725
    if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) {
343
4
      return false;
344
4
    }
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
721
    ELF_Half et = x.e_type;
353
721
    if (this->NeedSwap) {
354
184
      cmELFByteSwap(et);
355
184
    }
356
721
    if (!this->FileTypeValid(et)) {
357
419
      cmELFByteSwap(et);
358
419
      if (this->FileTypeValid(et)) {
359
        // The previous byte order guess was wrong.  Flip it.
360
389
        this->NeedSwap = !this->NeedSwap;
361
389
      }
362
419
    }
363
364
    // Fix the byte order of the header.
365
721
    if (this->NeedSwap) {
366
261
      this->ByteSwap(x);
367
261
    }
368
721
    return true;
369
725
  }
370
  bool Read(ELF_Shdr& x)
371
27.1M
  {
372
27.1M
    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
373
27.1M
        this->NeedSwap) {
374
7.83M
      this->ByteSwap(x);
375
7.83M
    }
376
27.1M
    return !this->Stream->fail();
377
27.1M
  }
cmELFInternalImpl<cmELFTypes32>::Read(Elf32_Shdr&)
Line
Count
Source
371
13.5M
  {
372
13.5M
    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
373
13.5M
        this->NeedSwap) {
374
1.25M
      this->ByteSwap(x);
375
1.25M
    }
376
13.5M
    return !this->Stream->fail();
377
13.5M
  }
cmELFInternalImpl<cmELFTypes64>::Read(Elf64_Shdr&)
Line
Count
Source
371
13.5M
  {
372
13.5M
    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
373
13.5M
        this->NeedSwap) {
374
6.57M
      this->ByteSwap(x);
375
6.57M
    }
376
13.5M
    return !this->Stream->fail();
377
13.5M
  }
378
  bool Read(ELF_Dyn& x)
379
1.91M
  {
380
1.91M
    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
381
1.91M
        this->NeedSwap) {
382
82.7k
      this->ByteSwap(x);
383
82.7k
    }
384
1.91M
    return !this->Stream->fail();
385
1.91M
  }
cmELFInternalImpl<cmELFTypes32>::Read(Elf32_Dyn&)
Line
Count
Source
379
1.69M
  {
380
1.69M
    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
381
1.69M
        this->NeedSwap) {
382
81.7k
      this->ByteSwap(x);
383
81.7k
    }
384
1.69M
    return !this->Stream->fail();
385
1.69M
  }
cmELFInternalImpl<cmELFTypes64>::Read(Elf64_Dyn&)
Line
Count
Source
379
219k
  {
380
219k
    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
381
219k
        this->NeedSwap) {
382
1.00k
      this->ByteSwap(x);
383
1.00k
    }
384
219k
    return !this->Stream->fail();
385
219k
  }
386
387
  bool LoadSectionHeader(std::size_t i)
388
27.1M
  {
389
    // Read the section header from the file.
390
27.1M
    this->Stream->seekg(this->ELFHeader.e_shoff +
391
27.1M
                        this->ELFHeader.e_shentsize * i);
392
27.1M
    if (!this->Read(this->SectionHeaders[i])) {
393
167
      this->SetErrorMessage("Failed to load section headers.");
394
167
      return false;
395
167
    }
396
397
    // Identify some important sections.
398
27.1M
    if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) {
399
21.6M
      this->DynamicSectionIndex = static_cast<int>(i);
400
21.6M
    }
401
27.1M
    return true;
402
27.1M
  }
cmELFInternalImpl<cmELFTypes32>::LoadSectionHeader(unsigned long)
Line
Count
Source
388
13.5M
  {
389
    // Read the section header from the file.
390
13.5M
    this->Stream->seekg(this->ELFHeader.e_shoff +
391
13.5M
                        this->ELFHeader.e_shentsize * i);
392
13.5M
    if (!this->Read(this->SectionHeaders[i])) {
393
54
      this->SetErrorMessage("Failed to load section headers.");
394
54
      return false;
395
54
    }
396
397
    // Identify some important sections.
398
13.5M
    if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) {
399
11.7M
      this->DynamicSectionIndex = static_cast<int>(i);
400
11.7M
    }
401
13.5M
    return true;
402
13.5M
  }
cmELFInternalImpl<cmELFTypes64>::LoadSectionHeader(unsigned long)
Line
Count
Source
388
13.5M
  {
389
    // Read the section header from the file.
390
13.5M
    this->Stream->seekg(this->ELFHeader.e_shoff +
391
13.5M
                        this->ELFHeader.e_shentsize * i);
392
13.5M
    if (!this->Read(this->SectionHeaders[i])) {
393
113
      this->SetErrorMessage("Failed to load section headers.");
394
113
      return false;
395
113
    }
396
397
    // Identify some important sections.
398
13.5M
    if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) {
399
9.95M
      this->DynamicSectionIndex = static_cast<int>(i);
400
9.95M
    }
401
13.5M
    return true;
402
13.5M
  }
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.17k
  : cmELFInternal(external, std::move(fin), order)
421
1.17k
{
422
  // Read the main header.
423
1.17k
  if (!this->Read(this->ELFHeader)) {
424
7
    this->SetErrorMessage("Failed to read main ELF header.");
425
7
    return;
426
7
  }
427
428
  // Determine the ELF file type.
429
1.16k
  switch (this->ELFHeader.e_type) {
430
2
    case ET_NONE:
431
2
      this->SetErrorMessage("ELF file type is NONE.");
432
2
      return;
433
54
    case ET_REL:
434
54
      this->ELFType = cmELF::FileTypeRelocatableObject;
435
54
      break;
436
363
    case ET_EXEC:
437
363
      this->ELFType = cmELF::FileTypeExecutable;
438
363
      break;
439
424
    case ET_DYN:
440
424
      this->ELFType = cmELF::FileTypeSharedLibrary;
441
424
      break;
442
35
    case ET_CORE:
443
35
      this->ELFType = cmELF::FileTypeCore;
444
35
      break;
445
291
    default: {
446
291
      unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
447
291
      if (eti >= ET_LOOS && eti <= ET_HIOS) {
448
51
        this->ELFType = cmELF::FileTypeSpecificOS;
449
51
        break;
450
51
      }
451
240
      if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
452
190
        this->ELFType = cmELF::FileTypeSpecificProc;
453
190
        break;
454
190
      }
455
50
      std::ostringstream e;
456
50
      e << "Unknown ELF file type " << eti;
457
50
      this->SetErrorMessage(e.str().c_str());
458
50
      return;
459
240
    }
460
1.16k
  }
461
462
1.11k
  this->Machine = this->ELFHeader.e_machine;
463
464
  // Load the section headers.
465
1.11k
  std::size_t const minSections = 1;
466
1.11k
  std::size_t numSections = this->ELFHeader.e_shnum;
467
  // Prevent OOM from malformed files.
468
1.11k
  if (numSections > kMaxSections) {
469
0
    this->SetErrorMessage("ELF file has too many sections.");
470
0
    return;
471
0
  }
472
1.11k
  this->SectionHeaders.resize(std::max(numSections, minSections));
473
1.11k
  if (!this->LoadSectionHeader(0)) {
474
22
    return;
475
22
  }
476
1.09k
  numSections = this->GetNumberOfSections();
477
1.09k
  this->SectionHeaders.resize(std::max(numSections, minSections));
478
27.1M
  for (std::size_t i = 1; i < numSections; ++i) {
479
27.1M
    if (!this->LoadSectionHeader(i)) {
480
145
      return;
481
145
    }
482
27.1M
  }
483
1.09k
}
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
451
  : cmELFInternal(external, std::move(fin), order)
421
451
{
422
  // Read the main header.
423
451
  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
448
  switch (this->ELFHeader.e_type) {
430
1
    case ET_NONE:
431
1
      this->SetErrorMessage("ELF file type is NONE.");
432
1
      return;
433
9
    case ET_REL:
434
9
      this->ELFType = cmELF::FileTypeRelocatableObject;
435
9
      break;
436
146
    case ET_EXEC:
437
146
      this->ELFType = cmELF::FileTypeExecutable;
438
146
      break;
439
163
    case ET_DYN:
440
163
      this->ELFType = cmELF::FileTypeSharedLibrary;
441
163
      break;
442
20
    case ET_CORE:
443
20
      this->ELFType = cmELF::FileTypeCore;
444
20
      break;
445
109
    default: {
446
109
      unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
447
109
      if (eti >= ET_LOOS && eti <= ET_HIOS) {
448
23
        this->ELFType = cmELF::FileTypeSpecificOS;
449
23
        break;
450
23
      }
451
86
      if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
452
66
        this->ELFType = cmELF::FileTypeSpecificProc;
453
66
        break;
454
66
      }
455
20
      std::ostringstream e;
456
20
      e << "Unknown ELF file type " << eti;
457
20
      this->SetErrorMessage(e.str().c_str());
458
20
      return;
459
86
    }
460
448
  }
461
462
427
  this->Machine = this->ELFHeader.e_machine;
463
464
  // Load the section headers.
465
427
  std::size_t const minSections = 1;
466
427
  std::size_t numSections = this->ELFHeader.e_shnum;
467
  // Prevent OOM from malformed files.
468
427
  if (numSections > kMaxSections) {
469
0
    this->SetErrorMessage("ELF file has too many sections.");
470
0
    return;
471
0
  }
472
427
  this->SectionHeaders.resize(std::max(numSections, minSections));
473
427
  if (!this->LoadSectionHeader(0)) {
474
13
    return;
475
13
  }
476
414
  numSections = this->GetNumberOfSections();
477
414
  this->SectionHeaders.resize(std::max(numSections, minSections));
478
13.5M
  for (std::size_t i = 1; i < numSections; ++i) {
479
13.5M
    if (!this->LoadSectionHeader(i)) {
480
41
      return;
481
41
    }
482
13.5M
  }
483
414
}
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
725
  : cmELFInternal(external, std::move(fin), order)
421
725
{
422
  // Read the main header.
423
725
  if (!this->Read(this->ELFHeader)) {
424
4
    this->SetErrorMessage("Failed to read main ELF header.");
425
4
    return;
426
4
  }
427
428
  // Determine the ELF file type.
429
721
  switch (this->ELFHeader.e_type) {
430
1
    case ET_NONE:
431
1
      this->SetErrorMessage("ELF file type is NONE.");
432
1
      return;
433
45
    case ET_REL:
434
45
      this->ELFType = cmELF::FileTypeRelocatableObject;
435
45
      break;
436
217
    case ET_EXEC:
437
217
      this->ELFType = cmELF::FileTypeExecutable;
438
217
      break;
439
261
    case ET_DYN:
440
261
      this->ELFType = cmELF::FileTypeSharedLibrary;
441
261
      break;
442
15
    case ET_CORE:
443
15
      this->ELFType = cmELF::FileTypeCore;
444
15
      break;
445
182
    default: {
446
182
      unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
447
182
      if (eti >= ET_LOOS && eti <= ET_HIOS) {
448
28
        this->ELFType = cmELF::FileTypeSpecificOS;
449
28
        break;
450
28
      }
451
154
      if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
452
124
        this->ELFType = cmELF::FileTypeSpecificProc;
453
124
        break;
454
124
      }
455
30
      std::ostringstream e;
456
30
      e << "Unknown ELF file type " << eti;
457
30
      this->SetErrorMessage(e.str().c_str());
458
30
      return;
459
154
    }
460
721
  }
461
462
690
  this->Machine = this->ELFHeader.e_machine;
463
464
  // Load the section headers.
465
690
  std::size_t const minSections = 1;
466
690
  std::size_t numSections = this->ELFHeader.e_shnum;
467
  // Prevent OOM from malformed files.
468
690
  if (numSections > kMaxSections) {
469
0
    this->SetErrorMessage("ELF file has too many sections.");
470
0
    return;
471
0
  }
472
690
  this->SectionHeaders.resize(std::max(numSections, minSections));
473
690
  if (!this->LoadSectionHeader(0)) {
474
9
    return;
475
9
  }
476
681
  numSections = this->GetNumberOfSections();
477
681
  this->SectionHeaders.resize(std::max(numSections, minSections));
478
13.5M
  for (std::size_t i = 1; i < numSections; ++i) {
479
13.5M
    if (!this->LoadSectionHeader(i)) {
480
104
      return;
481
104
    }
482
13.5M
  }
483
681
}
484
485
template <class Types>
486
bool cmELFInternalImpl<Types>::LoadDynamicSection()
487
11.0k
{
488
  // If there is no dynamic section we are done.
489
11.0k
  if (!this->HasDynamicSection()) {
490
247
    return false;
491
247
  }
492
493
  // If the section was already loaded we are done.
494
10.8k
  if (!this->DynamicSectionEntries.empty()) {
495
9.80k
    return true;
496
9.80k
  }
497
498
  // If there are no entries we are done.
499
1.02k
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
500
1.02k
  if (sec.sh_entsize == 0) {
501
28
    return false;
502
28
  }
503
504
  // Prevent OOM from malformed files.
505
996
  if (sec.sh_size > kMaxSectionSize) {
506
97
    this->SetErrorMessage("DYNAMIC section is too large.");
507
97
    return false;
508
97
  }
509
510
  // Allocate the dynamic section entries.
511
899
  std::size_t n = static_cast<int>(sec.sh_size / sec.sh_entsize);
512
  // Prevent OOM from malformed files.
513
899
  if (n > kMaxDynamicEntries) {
514
19
    this->SetErrorMessage("DYNAMIC section has too many entries.");
515
19
    return false;
516
19
  }
517
880
  this->DynamicSectionEntries.resize(n);
518
519
  // Read each entry.
520
1.91M
  for (std::size_t j = 0; j < n; ++j) {
521
    // Seek to the beginning of the section entry.
522
1.91M
    this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j);
523
1.91M
    ELF_Dyn& dyn = this->DynamicSectionEntries[j];
524
525
    // Try reading the entry.
526
1.91M
    if (!this->Read(dyn)) {
527
78
      this->SetErrorMessage("Error reading entry from DYNAMIC section.");
528
78
      this->DynamicSectionIndex = -1;
529
78
      return false;
530
78
    }
531
1.91M
  }
532
802
  return true;
533
880
}
cmELFInternalImpl<cmELFTypes32>::LoadDynamicSection()
Line
Count
Source
487
5.85k
{
488
  // If there is no dynamic section we are done.
489
5.85k
  if (!this->HasDynamicSection()) {
490
89
    return false;
491
89
  }
492
493
  // If the section was already loaded we are done.
494
5.76k
  if (!this->DynamicSectionEntries.empty()) {
495
5.35k
    return true;
496
5.35k
  }
497
498
  // If there are no entries we are done.
499
412
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
500
412
  if (sec.sh_entsize == 0) {
501
20
    return false;
502
20
  }
503
504
  // Prevent OOM from malformed files.
505
392
  if (sec.sh_size > kMaxSectionSize) {
506
18
    this->SetErrorMessage("DYNAMIC section is too large.");
507
18
    return false;
508
18
  }
509
510
  // Allocate the dynamic section entries.
511
374
  std::size_t n = static_cast<int>(sec.sh_size / sec.sh_entsize);
512
  // Prevent OOM from malformed files.
513
374
  if (n > kMaxDynamicEntries) {
514
10
    this->SetErrorMessage("DYNAMIC section has too many entries.");
515
10
    return false;
516
10
  }
517
364
  this->DynamicSectionEntries.resize(n);
518
519
  // Read each entry.
520
1.69M
  for (std::size_t j = 0; j < n; ++j) {
521
    // Seek to the beginning of the section entry.
522
1.69M
    this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j);
523
1.69M
    ELF_Dyn& dyn = this->DynamicSectionEntries[j];
524
525
    // Try reading the entry.
526
1.69M
    if (!this->Read(dyn)) {
527
48
      this->SetErrorMessage("Error reading entry from DYNAMIC section.");
528
48
      this->DynamicSectionIndex = -1;
529
48
      return false;
530
48
    }
531
1.69M
  }
532
316
  return true;
533
364
}
cmELFInternalImpl<cmELFTypes64>::LoadDynamicSection()
Line
Count
Source
487
5.21k
{
488
  // If there is no dynamic section we are done.
489
5.21k
  if (!this->HasDynamicSection()) {
490
158
    return false;
491
158
  }
492
493
  // If the section was already loaded we are done.
494
5.06k
  if (!this->DynamicSectionEntries.empty()) {
495
4.44k
    return true;
496
4.44k
  }
497
498
  // If there are no entries we are done.
499
612
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
500
612
  if (sec.sh_entsize == 0) {
501
8
    return false;
502
8
  }
503
504
  // Prevent OOM from malformed files.
505
604
  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
525
  std::size_t n = static_cast<int>(sec.sh_size / sec.sh_entsize);
512
  // Prevent OOM from malformed files.
513
525
  if (n > kMaxDynamicEntries) {
514
9
    this->SetErrorMessage("DYNAMIC section has too many entries.");
515
9
    return false;
516
9
  }
517
516
  this->DynamicSectionEntries.resize(n);
518
519
  // Read each entry.
520
220k
  for (std::size_t j = 0; j < n; ++j) {
521
    // Seek to the beginning of the section entry.
522
219k
    this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j);
523
219k
    ELF_Dyn& dyn = this->DynamicSectionEntries[j];
524
525
    // Try reading the entry.
526
219k
    if (!this->Read(dyn)) {
527
30
      this->SetErrorMessage("Error reading entry from DYNAMIC section.");
528
30
      this->DynamicSectionIndex = -1;
529
30
      return false;
530
30
    }
531
219k
  }
532
486
  return true;
533
516
}
534
535
template <class Types>
536
unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
537
9.18k
{
538
9.18k
  if (!this->LoadDynamicSection()) {
539
0
    return 0;
540
0
  }
541
9.18k
  if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) {
542
0
    return 0;
543
0
  }
544
9.18k
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
545
9.18k
  return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j);
546
9.18k
}
cmELFInternalImpl<cmELFTypes32>::GetDynamicEntryPosition(int)
Line
Count
Source
537
5.09k
{
538
5.09k
  if (!this->LoadDynamicSection()) {
539
0
    return 0;
540
0
  }
541
5.09k
  if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) {
542
0
    return 0;
543
0
  }
544
5.09k
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
545
5.09k
  return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j);
546
5.09k
}
cmELFInternalImpl<cmELFTypes64>::GetDynamicEntryPosition(int)
Line
Count
Source
537
4.08k
{
538
4.08k
  if (!this->LoadDynamicSection()) {
539
0
    return 0;
540
0
  }
541
4.08k
  if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) {
542
0
    return 0;
543
0
  }
544
4.08k
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
545
4.08k
  return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j);
546
4.08k
}
547
548
template <class Types>
549
cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries()
550
535
{
551
535
  cmELF::DynamicEntryList result;
552
553
  // Ensure entries have been read from file
554
535
  if (!this->LoadDynamicSection()) {
555
216
    return result;
556
216
  }
557
558
  // Copy into public array
559
319
  result.reserve(this->DynamicSectionEntries.size());
560
1.86M
  for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
561
1.86M
    result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
562
1.86M
  }
563
564
319
  return result;
565
535
}
cmELFInternalImpl<cmELFTypes32>::GetDynamicEntries()
Line
Count
Source
550
222
{
551
222
  cmELF::DynamicEntryList result;
552
553
  // Ensure entries have been read from file
554
222
  if (!this->LoadDynamicSection()) {
555
81
    return result;
556
81
  }
557
558
  // Copy into public array
559
141
  result.reserve(this->DynamicSectionEntries.size());
560
1.65M
  for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
561
1.65M
    result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
562
1.65M
  }
563
564
141
  return result;
565
222
}
cmELFInternalImpl<cmELFTypes64>::GetDynamicEntries()
Line
Count
Source
550
313
{
551
313
  cmELF::DynamicEntryList result;
552
553
  // Ensure entries have been read from file
554
313
  if (!this->LoadDynamicSection()) {
555
135
    return result;
556
135
  }
557
558
  // Copy into public array
559
178
  result.reserve(this->DynamicSectionEntries.size());
560
211k
  for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
561
211k
    result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
562
211k
  }
563
564
178
  return result;
565
313
}
566
567
template <class Types>
568
std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
569
  cmELF::DynamicEntryList const& entries)
570
192
{
571
192
  std::vector<char> result;
572
192
  result.reserve(sizeof(ELF_Dyn) * entries.size());
573
574
1.86M
  for (auto const& entry : entries) {
575
    // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars
576
1.86M
    ELF_Dyn dyn;
577
1.86M
    dyn.d_tag = static_cast<tagtype>(entry.first);
578
1.86M
    dyn.d_un.d_val = static_cast<tagtype>(entry.second);
579
580
1.86M
    if (this->NeedSwap) {
581
81.6k
      this->ByteSwap(dyn);
582
81.6k
    }
583
584
1.86M
    char* pdyn = reinterpret_cast<char*>(&dyn);
585
1.86M
    cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn));
586
1.86M
  }
587
588
192
  return result;
589
192
}
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
95
{
571
95
  std::vector<char> result;
572
95
  result.reserve(sizeof(ELF_Dyn) * entries.size());
573
574
1.65M
  for (auto const& entry : entries) {
575
    // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars
576
1.65M
    ELF_Dyn dyn;
577
1.65M
    dyn.d_tag = static_cast<tagtype>(entry.first);
578
1.65M
    dyn.d_un.d_val = static_cast<tagtype>(entry.second);
579
580
1.65M
    if (this->NeedSwap) {
581
80.8k
      this->ByteSwap(dyn);
582
80.8k
    }
583
584
1.65M
    char* pdyn = reinterpret_cast<char*>(&dyn);
585
1.65M
    cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn));
586
1.65M
  }
587
588
95
  return result;
589
95
}
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
97
{
571
97
  std::vector<char> result;
572
97
  result.reserve(sizeof(ELF_Dyn) * entries.size());
573
574
211k
  for (auto const& entry : entries) {
575
    // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars
576
211k
    ELF_Dyn dyn;
577
211k
    dyn.d_tag = static_cast<tagtype>(entry.first);
578
211k
    dyn.d_un.d_val = static_cast<tagtype>(entry.second);
579
580
211k
    if (this->NeedSwap) {
581
853
      this->ByteSwap(dyn);
582
853
    }
583
584
211k
    char* pdyn = reinterpret_cast<char*>(&dyn);
585
211k
    cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn));
586
211k
  }
587
588
97
  return result;
589
97
}
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
289
    if (dssi->second.Position > 0) {
599
77
      return &dssi->second;
600
77
    }
601
212
    return nullptr;
602
289
  }
603
604
  // Create an entry for this tag.  Assume it is missing until found.
605
1.35k
  StringEntry& se = this->DynamicSectionStrings[tag];
606
1.35k
  se.Position = 0;
607
1.35k
  se.Size = 0;
608
1.35k
  se.IndexInSection = -1;
609
610
  // Try reading the dynamic section.
611
1.35k
  if (!this->LoadDynamicSection()) {
612
253
    return nullptr;
613
253
  }
614
615
  // Get the string table referenced by the DYNAMIC section.
616
1.10k
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
617
1.10k
  if (sec.sh_link >= this->SectionHeaders.size()) {
618
105
    this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
619
105
    return nullptr;
620
105
  }
621
1.00k
  ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
622
623
  // Look for the requested entry.
624
1.00k
  for (auto di = this->DynamicSectionEntries.begin();
625
1.23M
       di != this->DynamicSectionEntries.end(); ++di) {
626
1.22M
    ELF_Dyn& dyn = *di;
627
1.22M
    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
360
      if (dyn.d_un.d_val >= strtab.sh_size) {
631
155
        this->SetErrorMessage("Section DYNAMIC references string beyond "
632
155
                              "the end of its string section.");
633
155
        return nullptr;
634
155
      }
635
636
      // Seek to the position reported by the entry.
637
205
      unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
638
205
      unsigned long last = first;
639
205
      unsigned long end = static_cast<unsigned long>(strtab.sh_size);
640
205
      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
205
      bool terminated = false;
648
205
      char c;
649
456k
      while (last != end && this->Stream->get(c) && !(terminated && c)) {
650
456k
        ++last;
651
456k
        if (c) {
652
455k
          se.Value += c;
653
455k
        } else {
654
943
          terminated = true;
655
943
        }
656
456k
      }
657
658
      // Make sure the whole value was read.
659
205
      if (!(*this->Stream)) {
660
34
        if (tag == cmELF::TagRPath) {
661
18
          this->SetErrorMessage(
662
18
            "Dynamic section specifies unreadable DT_RPATH");
663
18
        } else if (tag == cmELF::TagRunPath) {
664
5
          this->SetErrorMessage(
665
5
            "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
34
        se.Value = "";
674
34
        return nullptr;
675
34
      }
676
677
      // The value has been read successfully.  Report it.
678
171
      se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
679
171
      se.Size = last - first;
680
171
      se.IndexInSection =
681
171
        static_cast<int>(di - this->DynamicSectionEntries.begin());
682
171
      return &se;
683
205
    }
684
1.22M
  }
685
640
  return nullptr;
686
1.00k
}
cmELFInternalImpl<cmELFTypes32>::GetDynamicSectionString(unsigned int)
Line
Count
Source
594
638
{
595
  // Short-circuit if already checked.
596
638
  auto dssi = this->DynamicSectionStrings.find(tag);
597
638
  if (dssi != this->DynamicSectionStrings.end()) {
598
97
    if (dssi->second.Position > 0) {
599
34
      return &dssi->second;
600
34
    }
601
63
    return nullptr;
602
97
  }
603
604
  // Create an entry for this tag.  Assume it is missing until found.
605
541
  StringEntry& se = this->DynamicSectionStrings[tag];
606
541
  se.Position = 0;
607
541
  se.Size = 0;
608
541
  se.IndexInSection = -1;
609
610
  // Try reading the dynamic section.
611
541
  if (!this->LoadDynamicSection()) {
612
104
    return nullptr;
613
104
  }
614
615
  // Get the string table referenced by the DYNAMIC section.
616
437
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
617
437
  if (sec.sh_link >= this->SectionHeaders.size()) {
618
37
    this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
619
37
    return nullptr;
620
37
  }
621
400
  ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
622
623
  // Look for the requested entry.
624
400
  for (auto di = this->DynamicSectionEntries.begin();
625
706k
       di != this->DynamicSectionEntries.end(); ++di) {
626
706k
    ELF_Dyn& dyn = *di;
627
706k
    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
147
      if (dyn.d_un.d_val >= strtab.sh_size) {
631
52
        this->SetErrorMessage("Section DYNAMIC references string beyond "
632
52
                              "the end of its string section.");
633
52
        return nullptr;
634
52
      }
635
636
      // Seek to the position reported by the entry.
637
95
      unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
638
95
      unsigned long last = first;
639
95
      unsigned long end = static_cast<unsigned long>(strtab.sh_size);
640
95
      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
95
      bool terminated = false;
648
95
      char c;
649
396k
      while (last != end && this->Stream->get(c) && !(terminated && c)) {
650
396k
        ++last;
651
396k
        if (c) {
652
396k
          se.Value += c;
653
396k
        } else {
654
482
          terminated = true;
655
482
        }
656
396k
      }
657
658
      // Make sure the whole value was read.
659
95
      if (!(*this->Stream)) {
660
11
        if (tag == cmELF::TagRPath) {
661
7
          this->SetErrorMessage(
662
7
            "Dynamic section specifies unreadable DT_RPATH");
663
7
        } else if (tag == cmELF::TagRunPath) {
664
1
          this->SetErrorMessage(
665
1
            "Dynamic section specifies unreadable DT_RUNPATH");
666
3
        } else if (tag == cmELF::TagMipsRldMapRel) {
667
0
          this->SetErrorMessage(
668
0
            "Dynamic section specifies unreadable DT_MIPS_RLD_MAP_REL");
669
3
        } else {
670
3
          this->SetErrorMessage("Dynamic section specifies unreadable value"
671
3
                                " for unexpected attribute");
672
3
        }
673
11
        se.Value = "";
674
11
        return nullptr;
675
11
      }
676
677
      // The value has been read successfully.  Report it.
678
84
      se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
679
84
      se.Size = last - first;
680
84
      se.IndexInSection =
681
84
        static_cast<int>(di - this->DynamicSectionEntries.begin());
682
84
      return &se;
683
95
    }
684
706k
  }
685
253
  return nullptr;
686
400
}
cmELFInternalImpl<cmELFTypes64>::GetDynamicSectionString(unsigned int)
Line
Count
Source
594
1.00k
{
595
  // Short-circuit if already checked.
596
1.00k
  auto dssi = this->DynamicSectionStrings.find(tag);
597
1.00k
  if (dssi != this->DynamicSectionStrings.end()) {
598
192
    if (dssi->second.Position > 0) {
599
43
      return &dssi->second;
600
43
    }
601
149
    return nullptr;
602
192
  }
603
604
  // Create an entry for this tag.  Assume it is missing until found.
605
817
  StringEntry& se = this->DynamicSectionStrings[tag];
606
817
  se.Position = 0;
607
817
  se.Size = 0;
608
817
  se.IndexInSection = -1;
609
610
  // Try reading the dynamic section.
611
817
  if (!this->LoadDynamicSection()) {
612
149
    return nullptr;
613
149
  }
614
615
  // Get the string table referenced by the DYNAMIC section.
616
668
  ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
617
668
  if (sec.sh_link >= this->SectionHeaders.size()) {
618
68
    this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
619
68
    return nullptr;
620
68
  }
621
600
  ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
622
623
  // Look for the requested entry.
624
600
  for (auto di = this->DynamicSectionEntries.begin();
625
523k
       di != this->DynamicSectionEntries.end(); ++di) {
626
523k
    ELF_Dyn& dyn = *di;
627
523k
    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
213
      if (dyn.d_un.d_val >= strtab.sh_size) {
631
103
        this->SetErrorMessage("Section DYNAMIC references string beyond "
632
103
                              "the end of its string section.");
633
103
        return nullptr;
634
103
      }
635
636
      // Seek to the position reported by the entry.
637
110
      unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
638
110
      unsigned long last = first;
639
110
      unsigned long end = static_cast<unsigned long>(strtab.sh_size);
640
110
      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
110
      bool terminated = false;
648
110
      char c;
649
59.9k
      while (last != end && this->Stream->get(c) && !(terminated && c)) {
650
59.8k
        ++last;
651
59.8k
        if (c) {
652
59.4k
          se.Value += c;
653
59.4k
        } else {
654
461
          terminated = true;
655
461
        }
656
59.8k
      }
657
658
      // Make sure the whole value was read.
659
110
      if (!(*this->Stream)) {
660
23
        if (tag == cmELF::TagRPath) {
661
11
          this->SetErrorMessage(
662
11
            "Dynamic section specifies unreadable DT_RPATH");
663
12
        } else if (tag == cmELF::TagRunPath) {
664
4
          this->SetErrorMessage(
665
4
            "Dynamic section specifies unreadable DT_RUNPATH");
666
8
        } else if (tag == cmELF::TagMipsRldMapRel) {
667
0
          this->SetErrorMessage(
668
0
            "Dynamic section specifies unreadable DT_MIPS_RLD_MAP_REL");
669
8
        } else {
670
8
          this->SetErrorMessage("Dynamic section specifies unreadable value"
671
8
                                " for unexpected attribute");
672
8
        }
673
23
        se.Value = "";
674
23
        return nullptr;
675
23
      }
676
677
      // The value has been read successfully.  Report it.
678
87
      se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
679
87
      se.Size = last - first;
680
87
      se.IndexInSection =
681
87
        static_cast<int>(di - this->DynamicSectionEntries.begin());
682
87
      return &se;
683
110
    }
684
523k
  }
685
387
  return nullptr;
686
600
}
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.25k
{
697
  // Try to open the file.
698
1.25k
  auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary);
699
700
  // Quit now if the file could not be opened.
701
1.25k
  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.25k
  char ident[EI_NIDENT];
708
1.25k
  if (!fin->read(ident, EI_NIDENT)) {
709
0
    this->ErrorMessage = "Error reading ELF identification.";
710
0
    return;
711
0
  }
712
1.25k
  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.25k
  if (!(ident[EI_MAG0] == ELFMAG0 && ident[EI_MAG1] == ELFMAG1 &&
719
1.22k
        ident[EI_MAG2] == ELFMAG2 && ident[EI_MAG3] == ELFMAG3)) {
720
56
    this->ErrorMessage = "File does not have a valid ELF identification.";
721
56
    return;
722
56
  }
723
724
  // Check the byte order in which the rest of the file is encoded.
725
1.19k
  cmELFInternal::ByteOrderType order;
726
1.19k
  if (ident[EI_DATA] == ELFDATA2LSB) {
727
    // File is LSB.
728
947
    order = cmELFInternal::ByteOrderLSB;
729
947
  } else if (ident[EI_DATA] == ELFDATA2MSB) {
730
    // File is MSB.
731
240
    order = cmELFInternal::ByteOrderMSB;
732
240
  } 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.18k
  if (ident[EI_CLASS] == ELFCLASS32) {
740
    // 32-bit ELF
741
451
    this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>(
742
451
      this, std::move(fin), order);
743
736
  } else if (ident[EI_CLASS] == ELFCLASS64) {
744
    // 64-bit ELF
745
725
    this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>(
746
725
      this, std::move(fin), order);
747
725
  } else {
748
11
    this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
749
11
    return;
750
11
  }
751
1.18k
}
752
753
1.25k
cmELF::~cmELF() = default;
754
755
bool cmELF::Valid() const
756
21.0k
{
757
21.0k
  return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
758
21.0k
}
759
760
cmELF::FileType cmELF::GetFileType() const
761
950
{
762
950
  if (this->Valid()) {
763
950
    return this->Internal->GetFileType();
764
950
  }
765
0
  return FileTypeInvalid;
766
950
}
767
768
std::uint16_t cmELF::GetMachine() const
769
950
{
770
950
  if (this->Valid()) {
771
950
    return this->Internal->GetMachine();
772
950
  }
773
0
  return 0;
774
950
}
775
776
std::size_t cmELF::GetNumberOfSections() const
777
950
{
778
950
  if (this->Valid()) {
779
950
    return this->Internal->GetNumberOfSections();
780
950
  }
781
0
  return 0;
782
950
}
783
784
unsigned long cmELF::GetDynamicEntryPosition(int index) const
785
9.18k
{
786
9.18k
  if (this->Valid()) {
787
9.18k
    return this->Internal->GetDynamicEntryPosition(index);
788
9.18k
  }
789
0
  return 0;
790
9.18k
}
791
792
cmELF::DynamicEntryList cmELF::GetDynamicEntries() const
793
950
{
794
950
  if (this->Valid()) {
795
535
    return this->Internal->GetDynamicEntries();
796
535
  }
797
798
415
  return cmELF::DynamicEntryList();
799
950
}
800
801
std::vector<char> cmELF::EncodeDynamicEntries(
802
  cmELF::DynamicEntryList const& dentries) const
803
192
{
804
192
  if (this->Valid()) {
805
192
    return this->Internal->EncodeDynamicEntries(dentries);
806
192
  }
807
808
0
  return std::vector<char>();
809
192
}
810
811
bool cmELF::HasDynamicSection() const
812
950
{
813
950
  return this->Valid() && this->Internal->HasDynamicSection();
814
950
}
815
816
bool cmELF::GetSOName(std::string& soname)
817
950
{
818
950
  if (StringEntry const* se = this->GetSOName()) {
819
100
    soname = se->Value;
820
100
    return true;
821
100
  }
822
850
  return false;
823
950
}
824
825
cmELF::StringEntry const* cmELF::GetSOName()
826
1.90k
{
827
1.90k
  if (this->Valid() &&
828
1.79k
      this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) {
829
687
    return this->Internal->GetSOName();
830
687
  }
831
1.21k
  return nullptr;
832
1.90k
}
833
834
cmELF::StringEntry const* cmELF::GetRPath()
835
950
{
836
950
  if (this->Valid() &&
837
841
      (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
838
621
       this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
839
621
    return this->Internal->GetRPath();
840
621
  }
841
329
  return nullptr;
842
950
}
843
844
cmELF::StringEntry const* cmELF::GetRunPath()
845
950
{
846
950
  if (this->Valid() &&
847
559
      (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
848
401
       this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
849
339
    return this->Internal->GetRunPath();
850
339
  }
851
611
  return nullptr;
852
950
}
853
854
bool cmELF::IsMIPS() const
855
950
{
856
950
  if (this->Valid()) {
857
950
    return this->Internal->IsMips();
858
950
  }
859
0
  return false;
860
950
}
861
862
void cmELF::PrintInfo(std::ostream& os) const
863
950
{
864
950
  if (this->Valid()) {
865
462
    this->Internal->PrintInfo(os);
866
488
  } else {
867
488
    os << "Not a valid ELF file.\n";
868
488
  }
869
950
}