Coverage Report

Created: 2026-09-14 06:43

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