Coverage Report

Created: 2026-04-29 07:01

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