Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmELF.cxx
blob687a1c70bf81fba643c8f22088a4e24640820e50
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmELF.cxx,v $
5 Language: C++
6 Date: $Date: 2008-04-14 19:02:24 $
7 Version: $Revision: 1.9 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmStandardIncludes.h" // to get CMAKE_USE_ELF_PARSER first
18 #include "cmELF.h"
20 #include <cmsys/auto_ptr.hxx>
22 // Need the native byte order of the running CPU.
23 #include <cmsys/CPU.h>
25 // Include the ELF format information system header.
26 #include <elf.h>
27 #if defined(__sun)
28 # include <sys/link.h> // For dynamic section information
29 #endif
31 //----------------------------------------------------------------------------
32 // Low-level byte swapping implementation.
33 template <size_t s> struct cmELFByteSwapSize {};
34 void cmELFByteSwap(char*, cmELFByteSwapSize<1> const&)
37 void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const&)
39 char one_byte;
40 one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
42 void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const&)
44 char one_byte;
45 one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
46 one_byte = data[1]; data[1] = data[2]; data[2] = one_byte;
48 void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const&)
50 char one_byte;
51 one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
52 one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
53 one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
54 one_byte = data[3]; data[3] = data[4]; data[4] = one_byte;
57 // Low-level byte swapping interface.
58 template <typename T>
59 void cmELFByteSwap(T& x)
61 cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
64 //----------------------------------------------------------------------------
65 class cmELFInternal
67 public:
68 typedef cmELF::StringEntry StringEntry;
69 enum ByteOrderType { ByteOrderMSB, ByteOrderLSB };
71 // Construct and take ownership of the file stream object.
72 cmELFInternal(cmELF* external,
73 cmsys::auto_ptr<std::ifstream>& fin,
74 ByteOrderType order):
75 External(external),
76 Stream(*fin.release()),
77 ByteOrder(order),
78 ELFType(cmELF::FileTypeInvalid)
80 // In most cases the processor-specific byte order will match that
81 // of the target execution environment. If we choose wrong here
82 // it is fixed when the header is read.
83 #if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE
84 this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
85 #elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG
86 this->NeedSwap = (this->ByteOrder == ByteOrderLSB);
87 #endif
89 // We have not yet loaded the section info.
90 this->DynamicSectionIndex = -1;
93 // Destruct and delete the file stream object.
94 virtual ~cmELFInternal()
96 delete &this->Stream;
99 // Forward to the per-class implementation.
100 virtual unsigned int GetNumberOfSections() const = 0;
101 virtual unsigned int GetDynamicEntryCount() = 0;
102 virtual unsigned long GetDynamicEntryPosition(int j) = 0;
103 virtual StringEntry const* GetDynamicSectionString(int tag) = 0;
104 virtual void PrintInfo(std::ostream& os) const = 0;
106 bool ReadBytes(unsigned long pos, unsigned long size, char* buf)
108 this->Stream.seekg(pos);
109 this->Stream.read(buf, size);
110 return this->Stream?true:false;
113 // Lookup the SONAME in the DYNAMIC section.
114 StringEntry const* GetSOName()
116 return this->GetDynamicSectionString(DT_SONAME);
119 // Lookup the RPATH in the DYNAMIC section.
120 StringEntry const* GetRPath()
122 return this->GetDynamicSectionString(DT_RPATH);
125 // Lookup the RUNPATH in the DYNAMIC section.
126 StringEntry const* GetRunPath()
128 #if defined(DT_RUNPATH)
129 return this->GetDynamicSectionString(DT_RUNPATH);
130 #else
131 return 0;
132 #endif
135 // Return the recorded ELF type.
136 cmELF::FileType GetFileType() const { return this->ELFType; }
137 protected:
138 // Data common to all ELF class implementations.
140 // The external cmELF object.
141 cmELF* External;
143 // The stream from which to read.
144 std::istream& Stream;
146 // The byte order of the ELF file.
147 ByteOrderType ByteOrder;
149 // The ELF file type.
150 cmELF::FileType ELFType;
152 // Whether we need to byte-swap structures read from the stream.
153 bool NeedSwap;
155 // The section header index of the DYNAMIC section (-1 if none).
156 int DynamicSectionIndex;
158 // Helper methods for subclasses.
159 void SetErrorMessage(const char* msg)
161 this->External->ErrorMessage = msg;
162 this->ELFType = cmELF::FileTypeInvalid;
165 // Store string table entry states.
166 std::map<int, StringEntry> DynamicSectionStrings;
169 //----------------------------------------------------------------------------
170 // Configure the implementation template for 32-bit ELF files.
171 struct cmELFTypes32
173 typedef Elf32_Ehdr ELF_Ehdr;
174 typedef Elf32_Shdr ELF_Shdr;
175 typedef Elf32_Dyn ELF_Dyn;
176 typedef Elf32_Half ELF_Half;
177 static const char* GetName() { return "32-bit"; }
180 // Configure the implementation template for 32-bit ELF files.
181 struct cmELFTypes64
183 typedef Elf64_Ehdr ELF_Ehdr;
184 typedef Elf64_Shdr ELF_Shdr;
185 typedef Elf64_Dyn ELF_Dyn;
186 typedef Elf64_Half ELF_Half;
187 static const char* GetName() { return "64-bit"; }
190 //----------------------------------------------------------------------------
191 // Parser implementation template.
192 template <class Types>
193 class cmELFInternalImpl: public cmELFInternal
195 public:
196 // Copy the ELF file format types from our configuration parameter.
197 typedef typename Types::ELF_Ehdr ELF_Ehdr;
198 typedef typename Types::ELF_Shdr ELF_Shdr;
199 typedef typename Types::ELF_Dyn ELF_Dyn;
200 typedef typename Types::ELF_Half ELF_Half;
202 // Construct with a stream and byte swap indicator.
203 cmELFInternalImpl(cmELF* external,
204 cmsys::auto_ptr<std::ifstream>& fin,
205 ByteOrderType order);
207 // Return the number of sections as specified by the ELF header.
208 virtual unsigned int GetNumberOfSections() const
210 return static_cast<unsigned int>(this->ELFHeader.e_shnum);
213 // Get the file position and size of a dynamic section entry.
214 virtual unsigned int GetDynamicEntryCount();
215 virtual unsigned long GetDynamicEntryPosition(int j);
217 // Lookup a string from the dynamic section with the given tag.
218 virtual StringEntry const* GetDynamicSectionString(int tag);
220 // Print information about the ELF file.
221 virtual void PrintInfo(std::ostream& os) const
223 os << "ELF " << Types::GetName();
224 if(this->ByteOrder == ByteOrderMSB)
226 os << " MSB";
228 else if(this->ByteOrder == ByteOrderLSB)
230 os << " LSB";
232 switch(this->ELFType)
234 case cmELF::FileTypeInvalid:
235 os << " invalid file";
236 break;
237 case cmELF::FileTypeRelocatableObject:
238 os << " relocatable object";
239 break;
240 case cmELF::FileTypeExecutable:
241 os << " executable";
242 break;
243 case cmELF::FileTypeSharedLibrary:
244 os << " shared library";
245 break;
246 case cmELF::FileTypeCore:
247 os << " core file";
248 break;
249 case cmELF::FileTypeSpecificOS:
250 os << " os-specific type";
251 break;
252 case cmELF::FileTypeSpecificProc:
253 os << " processor-specific type";
254 break;
256 os << "\n";
259 private:
260 void ByteSwap(ELF_Ehdr& elf_header)
262 cmELFByteSwap(elf_header.e_type);
263 cmELFByteSwap(elf_header.e_machine);
264 cmELFByteSwap(elf_header.e_version);
265 cmELFByteSwap(elf_header.e_entry);
266 cmELFByteSwap(elf_header.e_phoff);
267 cmELFByteSwap(elf_header.e_shoff);
268 cmELFByteSwap(elf_header.e_flags);
269 cmELFByteSwap(elf_header.e_ehsize);
270 cmELFByteSwap(elf_header.e_phentsize);
271 cmELFByteSwap(elf_header.e_phnum);
272 cmELFByteSwap(elf_header.e_shentsize);
273 cmELFByteSwap(elf_header.e_shnum);
274 cmELFByteSwap(elf_header.e_shstrndx);
277 void ByteSwap(ELF_Shdr& sec_header)
279 cmELFByteSwap(sec_header.sh_name);
280 cmELFByteSwap(sec_header.sh_type);
281 cmELFByteSwap(sec_header.sh_flags);
282 cmELFByteSwap(sec_header.sh_addr);
283 cmELFByteSwap(sec_header.sh_offset);
284 cmELFByteSwap(sec_header.sh_size);
285 cmELFByteSwap(sec_header.sh_link);
286 cmELFByteSwap(sec_header.sh_info);
287 cmELFByteSwap(sec_header.sh_addralign);
288 cmELFByteSwap(sec_header.sh_entsize);
291 void ByteSwap(ELF_Dyn& dyn)
293 cmELFByteSwap(dyn.d_tag);
294 switch (dyn.d_tag)
296 case DT_NULL: /* dyn.d_un ignored */ break;
297 case DT_NEEDED: cmELFByteSwap(dyn.d_un.d_val); break;
298 case DT_PLTRELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
299 case DT_PLTGOT: cmELFByteSwap(dyn.d_un.d_ptr); break;
300 case DT_HASH: cmELFByteSwap(dyn.d_un.d_ptr); break;
301 case DT_STRTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
302 case DT_SYMTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
303 case DT_RELA: cmELFByteSwap(dyn.d_un.d_ptr); break;
304 case DT_RELASZ: cmELFByteSwap(dyn.d_un.d_val); break;
305 case DT_RELAENT: cmELFByteSwap(dyn.d_un.d_val); break;
306 case DT_STRSZ: cmELFByteSwap(dyn.d_un.d_val); break;
307 case DT_SYMENT: cmELFByteSwap(dyn.d_un.d_val); break;
308 case DT_INIT: cmELFByteSwap(dyn.d_un.d_ptr); break;
309 case DT_FINI: cmELFByteSwap(dyn.d_un.d_ptr); break;
310 case DT_SONAME: cmELFByteSwap(dyn.d_un.d_val); break;
311 case DT_RPATH: cmELFByteSwap(dyn.d_un.d_val); break;
312 case DT_SYMBOLIC: /* dyn.d_un ignored */ break;
313 case DT_REL: cmELFByteSwap(dyn.d_un.d_ptr); break;
314 case DT_RELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
315 case DT_RELENT: cmELFByteSwap(dyn.d_un.d_val); break;
316 case DT_PLTREL: cmELFByteSwap(dyn.d_un.d_val); break;
317 case DT_DEBUG: cmELFByteSwap(dyn.d_un.d_ptr); break;
318 case DT_TEXTREL: /* dyn.d_un ignored */ break;
319 case DT_JMPREL: cmELFByteSwap(dyn.d_un.d_ptr); break;
320 #ifdef T_BIND_NOW
321 case T_BIND_NOW: /* dyn.d_un ignored */ break;
322 #endif
323 #ifdef DT_INIT_ARRAY
324 case DT_INIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
325 #endif
326 #ifdef DT_FINI_ARRAY
327 case DT_FINI_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
328 #endif
329 #ifdef DT_INIT_ARRAYSZ
330 case DT_INIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
331 #endif
332 #ifdef DT_FINI_ARRAYSZ
333 case DT_FINI_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
334 #endif
335 #ifdef DT_RUNPATH
336 case DT_RUNPATH: cmELFByteSwap(dyn.d_un.d_val); break;
337 #endif
338 #ifdef DT_FLAGS
339 case DT_FLAGS: cmELFByteSwap(dyn.d_un.d_val); break;
340 #endif
341 #ifdef DT_PREINIT_ARRAY
342 case DT_PREINIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
343 #endif
344 #ifdef DT_PREINIT_ARRAYSZ
345 case DT_PREINIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
346 #endif
350 bool FileTypeValid(ELF_Half et)
352 unsigned int eti = static_cast<unsigned int>(et);
353 if(eti == ET_NONE || eti == ET_REL || eti == ET_EXEC ||
354 eti == ET_DYN || eti == ET_CORE)
356 return true;
358 #if defined(ET_LOOS) && defined(ET_HIOS)
359 if(eti >= ET_LOOS && eti <= ET_HIOS)
361 return true;
363 #endif
364 #if defined(ET_LOPROC) && defined(ET_HIPROC)
365 if(eti >= ET_LOPROC && eti <= ET_HIPROC)
367 return true;
369 #endif
370 return false;
373 bool Read(ELF_Ehdr& x)
375 // Read the header from the file.
376 if(!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)))
378 return false;
381 // The byte order of ELF header fields may not match that of the
382 // processor-specific data. The header fields are ordered to
383 // match the target execution environment, so we may need to
384 // memorize the order of all platforms based on the e_machine
385 // value. As a heuristic, if the type is invalid but its
386 // swapped value is okay then flip our swap mode.
387 ELF_Half et = x.e_type;
388 if(this->NeedSwap)
390 cmELFByteSwap(et);
392 if(!this->FileTypeValid(et))
394 cmELFByteSwap(et);
395 if(this->FileTypeValid(et))
397 // The previous byte order guess was wrong. Flip it.
398 this->NeedSwap = !this->NeedSwap;
402 // Fix the byte order of the header.
403 if(this->NeedSwap)
405 ByteSwap(x);
407 return true;
409 bool Read(ELF_Shdr& x)
411 if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
412 this->NeedSwap)
414 ByteSwap(x);
416 return this->Stream? true:false;
418 bool Read(ELF_Dyn& x)
420 if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
421 this->NeedSwap)
423 ByteSwap(x);
425 return this->Stream? true:false;
428 bool LoadSectionHeader(ELF_Half i)
430 // Read the section header from the file.
431 this->Stream.seekg(this->ELFHeader.e_shoff +
432 this->ELFHeader.e_shentsize * i);
433 if(!this->Read(this->SectionHeaders[i]))
435 return false;
438 // Identify some important sections.
439 if(this->SectionHeaders[i].sh_type == SHT_DYNAMIC)
441 this->DynamicSectionIndex = i;
443 return true;
446 bool LoadDynamicSection();
448 // Store the main ELF header.
449 ELF_Ehdr ELFHeader;
451 // Store all the section headers.
452 std::vector<ELF_Shdr> SectionHeaders;
454 // Store all entries of the DYNAMIC section.
455 std::vector<ELF_Dyn> DynamicSectionEntries;
458 //----------------------------------------------------------------------------
459 template <class Types>
460 cmELFInternalImpl<Types>
461 ::cmELFInternalImpl(cmELF* external,
462 cmsys::auto_ptr<std::ifstream>& fin,
463 ByteOrderType order):
464 cmELFInternal(external, fin, order)
466 // Read the main header.
467 if(!this->Read(this->ELFHeader))
469 this->SetErrorMessage("Failed to read main ELF header.");
470 return;
473 // Determine the ELF file type.
474 switch(this->ELFHeader.e_type)
476 case ET_NONE:
477 this->SetErrorMessage("ELF file type is NONE.");
478 return;
479 case ET_REL:
480 this->ELFType = cmELF::FileTypeRelocatableObject;
481 break;
482 case ET_EXEC:
483 this->ELFType = cmELF::FileTypeExecutable;
484 break;
485 case ET_DYN:
486 this->ELFType = cmELF::FileTypeSharedLibrary;
487 break;
488 case ET_CORE:
489 this->ELFType = cmELF::FileTypeCore;
490 break;
491 default:
493 unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
494 #if defined(ET_LOOS) && defined(ET_HIOS)
495 if(eti >= ET_LOOS && eti <= ET_HIOS)
497 this->ELFType = cmELF::FileTypeSpecificOS;
498 break;
500 #endif
501 #if defined(ET_LOPROC) && defined(ET_HIPROC)
502 if(eti >= ET_LOPROC && eti <= ET_HIPROC)
504 this->ELFType = cmELF::FileTypeSpecificProc;
505 break;
507 #endif
508 cmOStringStream e;
509 e << "Unknown ELF file type " << eti;
510 this->SetErrorMessage(e.str().c_str());
511 return;
515 // Load the section headers.
516 this->SectionHeaders.resize(this->ELFHeader.e_shnum);
517 for(ELF_Half i=0; i < this->ELFHeader.e_shnum; ++i)
519 if(!this->LoadSectionHeader(i))
521 this->SetErrorMessage("Failed to load section headers.");
522 return;
527 //----------------------------------------------------------------------------
528 template <class Types>
529 bool cmELFInternalImpl<Types>::LoadDynamicSection()
531 // If there is no dynamic section we are done.
532 if(this->DynamicSectionIndex < 0)
534 return false;
537 // If the section was already loaded we are done.
538 if(!this->DynamicSectionEntries.empty())
540 return true;
543 // Allocate the dynamic section entries.
544 ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
545 int n = sec.sh_size / sec.sh_entsize;
546 this->DynamicSectionEntries.resize(n);
548 // Read each entry.
549 for(int j=0; j < n; ++j)
551 // Seek to the beginning of the section entry.
552 this->Stream.seekg(sec.sh_offset + sec.sh_entsize*j);
553 ELF_Dyn& dyn = this->DynamicSectionEntries[j];
555 // Try reading the entry.
556 if(!this->Read(dyn))
558 this->SetErrorMessage("Error reading entry from DYNAMIC section.");
559 this->DynamicSectionIndex = -1;
560 return false;
563 return true;
566 //----------------------------------------------------------------------------
567 template <class Types>
568 unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount()
570 if(!this->LoadDynamicSection())
572 return 0;
574 for(unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i)
576 if(this->DynamicSectionEntries[i].d_tag == DT_NULL)
578 return i;
581 return this->DynamicSectionEntries.size();
584 //----------------------------------------------------------------------------
585 template <class Types>
586 unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
588 if(!this->LoadDynamicSection())
590 return 0;
592 if(j < 0 || j >= this->DynamicSectionEntries.size())
594 return 0;
596 ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
597 return sec.sh_offset + sec.sh_entsize*j;
600 //----------------------------------------------------------------------------
601 template <class Types>
602 cmELF::StringEntry const*
603 cmELFInternalImpl<Types>::GetDynamicSectionString(int tag)
605 // Short-circuit if already checked.
606 std::map<int, StringEntry>::iterator dssi =
607 this->DynamicSectionStrings.find(tag);
608 if(dssi != this->DynamicSectionStrings.end())
610 if(dssi->second.Position > 0)
612 return &dssi->second;
614 return 0;
617 // Create an entry for this tag. Assume it is missing until found.
618 StringEntry& se = this->DynamicSectionStrings[tag];
619 se.Position = 0;
620 se.Size = 0;
621 se.IndexInSection = -1;
623 // Try reading the dynamic section.
624 if(!this->LoadDynamicSection())
626 return 0;
629 // Get the string table referenced by the DYNAMIC section.
630 ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
631 if(sec.sh_link >= this->SectionHeaders.size())
633 this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
634 return 0;
636 ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
638 // Look for the requested entry.
639 for(typename std::vector<ELF_Dyn>::iterator
640 di = this->DynamicSectionEntries.begin();
641 di != this->DynamicSectionEntries.end(); ++di)
643 ELF_Dyn& dyn = *di;
644 if(dyn.d_tag == tag)
646 // We found the tag requested.
647 // Make sure the position given is within the string section.
648 if(dyn.d_un.d_val >= strtab.sh_size)
650 this->SetErrorMessage("Section DYNAMIC references string beyond "
651 "the end of its string section.");
652 return 0;
655 // Seek to the position reported by the entry.
656 unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
657 unsigned long last = first;
658 unsigned long end = static_cast<unsigned long>(strtab.sh_size);
659 this->Stream.seekg(strtab.sh_offset + first);
661 // Read the string. It may be followed by more than one NULL
662 // terminator. Count the total size of the region allocated to
663 // the string. This assumes that the next string in the table
664 // is non-empty, but the "chrpath" tool makes the same
665 // assumption.
666 bool terminated = false;
667 char c;
668 while(last != end && this->Stream.get(c) && !(terminated && c))
670 ++last;
671 if(c)
673 se.Value += c;
675 else
677 terminated = true;
681 // Make sure the whole value was read.
682 if(!this->Stream)
684 this->SetErrorMessage("Dynamic section specifies unreadable RPATH.");
685 se.Value = "";
686 return 0;
689 // The value has been read successfully. Report it.
690 se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
691 se.Size = last - first;
692 se.IndexInSection = di - this->DynamicSectionEntries.begin();
693 return &se;
696 return 0;
699 //============================================================================
700 // External class implementation.
702 //----------------------------------------------------------------------------
703 cmELF::cmELF(const char* fname): Internal(0)
705 // Try to open the file.
706 cmsys::auto_ptr<std::ifstream> fin(new std::ifstream(fname));
708 // Quit now if the file could not be opened.
709 if(!fin.get() || !*fin)
711 this->ErrorMessage = "Error opening input file.";
712 return;
715 // Read the ELF identification block.
716 char ident[EI_NIDENT];
717 if(!fin->read(ident, EI_NIDENT))
719 this->ErrorMessage = "Error reading ELF identification.";
720 return;
722 if(!fin->seekg(0))
724 this->ErrorMessage = "Error seeking to beginning of file.";
725 return;
728 // Verify the ELF identification.
729 if(!(ident[EI_MAG0] == ELFMAG0 &&
730 ident[EI_MAG1] == ELFMAG1 &&
731 ident[EI_MAG2] == ELFMAG2 &&
732 ident[EI_MAG3] == ELFMAG3))
734 this->ErrorMessage = "File does not have a valid ELF identification.";
735 return;
738 // Check the byte order in which the rest of the file is encoded.
739 cmELFInternal::ByteOrderType order;
740 if(ident[EI_DATA] == ELFDATA2LSB)
742 // File is LSB.
743 order = cmELFInternal::ByteOrderLSB;
745 else if(ident[EI_DATA] == ELFDATA2MSB)
747 // File is MSB.
748 order = cmELFInternal::ByteOrderMSB;
750 else
752 this->ErrorMessage = "ELF file is not LSB or MSB encoded.";
753 return;
756 // Check the class of the file and construct the corresponding
757 // parser implementation.
758 if(ident[EI_CLASS] == ELFCLASS32)
760 // 32-bit ELF
761 this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
763 else if(ident[EI_CLASS] == ELFCLASS64)
765 // 64-bit ELF
766 this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
768 else
770 this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
771 return;
775 //----------------------------------------------------------------------------
776 cmELF::~cmELF()
778 delete this->Internal;
781 //----------------------------------------------------------------------------
782 bool cmELF::Valid() const
784 return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
787 //----------------------------------------------------------------------------
788 cmELF::FileType cmELF::GetFileType() const
790 if(this->Valid())
792 return this->Internal->GetFileType();
794 else
796 return FileTypeInvalid;
800 //----------------------------------------------------------------------------
801 unsigned int cmELF::GetNumberOfSections() const
803 if(this->Valid())
805 return this->Internal->GetNumberOfSections();
807 else
809 return 0;
813 //----------------------------------------------------------------------------
814 unsigned int cmELF::GetDynamicEntryCount() const
816 if(this->Valid())
818 return this->Internal->GetDynamicEntryCount();
820 else
822 return 0;
826 //----------------------------------------------------------------------------
827 unsigned long cmELF::GetDynamicEntryPosition(int index) const
829 if(this->Valid())
831 return this->Internal->GetDynamicEntryPosition(index);
833 else
835 return 0;
839 //----------------------------------------------------------------------------
840 bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const
842 if(this->Valid())
844 return this->Internal->ReadBytes(pos, size, buf);
846 else
848 return false;
852 //----------------------------------------------------------------------------
853 bool cmELF::GetSOName(std::string& soname)
855 if(StringEntry const* se = this->GetSOName())
857 soname = se->Value;
858 return true;
860 else
862 return false;
866 //----------------------------------------------------------------------------
867 cmELF::StringEntry const* cmELF::GetSOName()
869 if(this->Valid() &&
870 this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)
872 return this->Internal->GetSOName();
874 else
876 return 0;
880 //----------------------------------------------------------------------------
881 cmELF::StringEntry const* cmELF::GetRPath()
883 if(this->Valid() &&
884 this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
885 this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)
887 return this->Internal->GetRPath();
889 else
891 return 0;
895 //----------------------------------------------------------------------------
896 cmELF::StringEntry const* cmELF::GetRunPath()
898 if(this->Valid() &&
899 this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
900 this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)
902 return this->Internal->GetRunPath();
904 else
906 return 0;
910 //----------------------------------------------------------------------------
911 void cmELF::PrintInfo(std::ostream& os) const
913 if(this->Valid())
915 this->Internal->PrintInfo(os);
917 else
919 os << "Not a valid ELF file.\n";