ENH: check in almost building VMS stuff with VMSBuild directory since the bootstrap...
[cmake.git] / Source / cmELF.cxx
blob4c22509de5bc694c5868ed355e4bba7f5bb20667
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmELF.cxx,v $
5 Language: C++
6 Date: $Date: 2008-08-04 13:38:38 $
7 Version: $Revision: 1.13 $
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 #define cmsys_CPU_UNKNOWN_OKAY // We can decide at runtime if not known.
24 #include <cmsys/CPU.h>
26 // Include the ELF format information system header.
27 #include <elf.h>
28 #if defined(__sun)
29 # include <sys/link.h> // For dynamic section information
30 #endif
32 //----------------------------------------------------------------------------
33 // Low-level byte swapping implementation.
34 template <size_t s> struct cmELFByteSwapSize {};
35 void cmELFByteSwap(char*, cmELFByteSwapSize<1> const&)
38 void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const&)
40 char one_byte;
41 one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
43 void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const&)
45 char one_byte;
46 one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
47 one_byte = data[1]; data[1] = data[2]; data[2] = one_byte;
49 void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const&)
51 char one_byte;
52 one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
53 one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
54 one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
55 one_byte = data[3]; data[3] = data[4]; data[4] = one_byte;
58 // Low-level byte swapping interface.
59 template <typename T>
60 void cmELFByteSwap(T& x)
62 cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
65 //----------------------------------------------------------------------------
66 class cmELFInternal
68 public:
69 typedef cmELF::StringEntry StringEntry;
70 enum ByteOrderType { ByteOrderMSB, ByteOrderLSB };
72 // Construct and take ownership of the file stream object.
73 cmELFInternal(cmELF* external,
74 cmsys::auto_ptr<std::ifstream>& fin,
75 ByteOrderType order):
76 External(external),
77 Stream(*fin.release()),
78 ByteOrder(order),
79 ELFType(cmELF::FileTypeInvalid)
81 // In most cases the processor-specific byte order will match that
82 // of the target execution environment. If we choose wrong here
83 // it is fixed when the header is read.
84 #if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE
85 this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
86 #elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG
87 this->NeedSwap = (this->ByteOrder == ByteOrderLSB);
88 #else
89 this->NeedSwap = false; // Final decision is at runtime anyway.
90 #endif
92 // We have not yet loaded the section info.
93 this->DynamicSectionIndex = -1;
96 // Destruct and delete the file stream object.
97 virtual ~cmELFInternal()
99 delete &this->Stream;
102 // Forward to the per-class implementation.
103 virtual unsigned int GetNumberOfSections() const = 0;
104 virtual unsigned int GetDynamicEntryCount() = 0;
105 virtual unsigned long GetDynamicEntryPosition(int j) = 0;
106 virtual StringEntry const* GetDynamicSectionString(int tag) = 0;
107 virtual void PrintInfo(std::ostream& os) const = 0;
109 bool ReadBytes(unsigned long pos, unsigned long size, char* buf)
111 this->Stream.seekg(pos);
112 this->Stream.read(buf, size);
113 return this->Stream?true:false;
116 // Lookup the SONAME in the DYNAMIC section.
117 StringEntry const* GetSOName()
119 return this->GetDynamicSectionString(DT_SONAME);
122 // Lookup the RPATH in the DYNAMIC section.
123 StringEntry const* GetRPath()
125 return this->GetDynamicSectionString(DT_RPATH);
128 // Lookup the RUNPATH in the DYNAMIC section.
129 StringEntry const* GetRunPath()
131 #if defined(DT_RUNPATH)
132 return this->GetDynamicSectionString(DT_RUNPATH);
133 #else
134 return 0;
135 #endif
138 // Return the recorded ELF type.
139 cmELF::FileType GetFileType() const { return this->ELFType; }
140 protected:
141 // Data common to all ELF class implementations.
143 // The external cmELF object.
144 cmELF* External;
146 // The stream from which to read.
147 std::istream& Stream;
149 // The byte order of the ELF file.
150 ByteOrderType ByteOrder;
152 // The ELF file type.
153 cmELF::FileType ELFType;
155 // Whether we need to byte-swap structures read from the stream.
156 bool NeedSwap;
158 // The section header index of the DYNAMIC section (-1 if none).
159 int DynamicSectionIndex;
161 // Helper methods for subclasses.
162 void SetErrorMessage(const char* msg)
164 this->External->ErrorMessage = msg;
165 this->ELFType = cmELF::FileTypeInvalid;
168 // Store string table entry states.
169 std::map<int, StringEntry> DynamicSectionStrings;
172 //----------------------------------------------------------------------------
173 // Configure the implementation template for 32-bit ELF files.
174 struct cmELFTypes32
176 typedef Elf32_Ehdr ELF_Ehdr;
177 typedef Elf32_Shdr ELF_Shdr;
178 typedef Elf32_Dyn ELF_Dyn;
179 typedef Elf32_Half ELF_Half;
180 static const char* GetName() { return "32-bit"; }
183 // Configure the implementation template for 32-bit ELF files.
184 struct cmELFTypes64
186 typedef Elf64_Ehdr ELF_Ehdr;
187 typedef Elf64_Shdr ELF_Shdr;
188 typedef Elf64_Dyn ELF_Dyn;
189 typedef Elf64_Half ELF_Half;
190 static const char* GetName() { return "64-bit"; }
193 //----------------------------------------------------------------------------
194 // Parser implementation template.
195 template <class Types>
196 class cmELFInternalImpl: public cmELFInternal
198 public:
199 // Copy the ELF file format types from our configuration parameter.
200 typedef typename Types::ELF_Ehdr ELF_Ehdr;
201 typedef typename Types::ELF_Shdr ELF_Shdr;
202 typedef typename Types::ELF_Dyn ELF_Dyn;
203 typedef typename Types::ELF_Half ELF_Half;
205 // Construct with a stream and byte swap indicator.
206 cmELFInternalImpl(cmELF* external,
207 cmsys::auto_ptr<std::ifstream>& fin,
208 ByteOrderType order);
210 // Return the number of sections as specified by the ELF header.
211 virtual unsigned int GetNumberOfSections() const
213 return static_cast<unsigned int>(this->ELFHeader.e_shnum);
216 // Get the file position and size of a dynamic section entry.
217 virtual unsigned int GetDynamicEntryCount();
218 virtual unsigned long GetDynamicEntryPosition(int j);
220 // Lookup a string from the dynamic section with the given tag.
221 virtual StringEntry const* GetDynamicSectionString(int tag);
223 // Print information about the ELF file.
224 virtual void PrintInfo(std::ostream& os) const
226 os << "ELF " << Types::GetName();
227 if(this->ByteOrder == ByteOrderMSB)
229 os << " MSB";
231 else if(this->ByteOrder == ByteOrderLSB)
233 os << " LSB";
235 switch(this->ELFType)
237 case cmELF::FileTypeInvalid:
238 os << " invalid file";
239 break;
240 case cmELF::FileTypeRelocatableObject:
241 os << " relocatable object";
242 break;
243 case cmELF::FileTypeExecutable:
244 os << " executable";
245 break;
246 case cmELF::FileTypeSharedLibrary:
247 os << " shared library";
248 break;
249 case cmELF::FileTypeCore:
250 os << " core file";
251 break;
252 case cmELF::FileTypeSpecificOS:
253 os << " os-specific type";
254 break;
255 case cmELF::FileTypeSpecificProc:
256 os << " processor-specific type";
257 break;
259 os << "\n";
262 private:
263 void ByteSwap(ELF_Ehdr& elf_header)
265 cmELFByteSwap(elf_header.e_type);
266 cmELFByteSwap(elf_header.e_machine);
267 cmELFByteSwap(elf_header.e_version);
268 cmELFByteSwap(elf_header.e_entry);
269 cmELFByteSwap(elf_header.e_phoff);
270 cmELFByteSwap(elf_header.e_shoff);
271 cmELFByteSwap(elf_header.e_flags);
272 cmELFByteSwap(elf_header.e_ehsize);
273 cmELFByteSwap(elf_header.e_phentsize);
274 cmELFByteSwap(elf_header.e_phnum);
275 cmELFByteSwap(elf_header.e_shentsize);
276 cmELFByteSwap(elf_header.e_shnum);
277 cmELFByteSwap(elf_header.e_shstrndx);
280 void ByteSwap(ELF_Shdr& sec_header)
282 cmELFByteSwap(sec_header.sh_name);
283 cmELFByteSwap(sec_header.sh_type);
284 cmELFByteSwap(sec_header.sh_flags);
285 cmELFByteSwap(sec_header.sh_addr);
286 cmELFByteSwap(sec_header.sh_offset);
287 cmELFByteSwap(sec_header.sh_size);
288 cmELFByteSwap(sec_header.sh_link);
289 cmELFByteSwap(sec_header.sh_info);
290 cmELFByteSwap(sec_header.sh_addralign);
291 cmELFByteSwap(sec_header.sh_entsize);
294 void ByteSwap(ELF_Dyn& dyn)
296 cmELFByteSwap(dyn.d_tag);
297 switch (dyn.d_tag)
299 case DT_NULL: /* dyn.d_un ignored */ break;
300 case DT_NEEDED: cmELFByteSwap(dyn.d_un.d_val); break;
301 case DT_PLTRELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
302 case DT_PLTGOT: cmELFByteSwap(dyn.d_un.d_ptr); break;
303 case DT_HASH: cmELFByteSwap(dyn.d_un.d_ptr); break;
304 case DT_STRTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
305 case DT_SYMTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
306 case DT_RELA: cmELFByteSwap(dyn.d_un.d_ptr); break;
307 case DT_RELASZ: cmELFByteSwap(dyn.d_un.d_val); break;
308 case DT_RELAENT: cmELFByteSwap(dyn.d_un.d_val); break;
309 case DT_STRSZ: cmELFByteSwap(dyn.d_un.d_val); break;
310 case DT_SYMENT: cmELFByteSwap(dyn.d_un.d_val); break;
311 case DT_INIT: cmELFByteSwap(dyn.d_un.d_ptr); break;
312 case DT_FINI: cmELFByteSwap(dyn.d_un.d_ptr); break;
313 case DT_SONAME: cmELFByteSwap(dyn.d_un.d_val); break;
314 case DT_RPATH: cmELFByteSwap(dyn.d_un.d_val); break;
315 case DT_SYMBOLIC: /* dyn.d_un ignored */ break;
316 case DT_REL: cmELFByteSwap(dyn.d_un.d_ptr); break;
317 case DT_RELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
318 case DT_RELENT: cmELFByteSwap(dyn.d_un.d_val); break;
319 case DT_PLTREL: cmELFByteSwap(dyn.d_un.d_val); break;
320 case DT_DEBUG: cmELFByteSwap(dyn.d_un.d_ptr); break;
321 case DT_TEXTREL: /* dyn.d_un ignored */ break;
322 case DT_JMPREL: cmELFByteSwap(dyn.d_un.d_ptr); break;
323 #ifdef T_BIND_NOW
324 case T_BIND_NOW: /* dyn.d_un ignored */ break;
325 #endif
326 #ifdef DT_INIT_ARRAY
327 case DT_INIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
328 #endif
329 #ifdef DT_FINI_ARRAY
330 case DT_FINI_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
331 #endif
332 #ifdef DT_INIT_ARRAYSZ
333 case DT_INIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
334 #endif
335 #ifdef DT_FINI_ARRAYSZ
336 case DT_FINI_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
337 #endif
338 #ifdef DT_RUNPATH
339 case DT_RUNPATH: cmELFByteSwap(dyn.d_un.d_val); break;
340 #endif
341 #ifdef DT_FLAGS
342 case DT_FLAGS: cmELFByteSwap(dyn.d_un.d_val); break;
343 #endif
344 #ifdef DT_PREINIT_ARRAY
345 case DT_PREINIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
346 #endif
347 #ifdef DT_PREINIT_ARRAYSZ
348 case DT_PREINIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
349 #endif
353 bool FileTypeValid(ELF_Half et)
355 unsigned int eti = static_cast<unsigned int>(et);
356 if(eti == ET_NONE || eti == ET_REL || eti == ET_EXEC ||
357 eti == ET_DYN || eti == ET_CORE)
359 return true;
361 #if defined(ET_LOOS) && defined(ET_HIOS)
362 if(eti >= ET_LOOS && eti <= ET_HIOS)
364 return true;
366 #endif
367 #if defined(ET_LOPROC) && defined(ET_HIPROC)
368 if(eti >= ET_LOPROC && eti <= ET_HIPROC)
370 return true;
372 #endif
373 return false;
376 bool Read(ELF_Ehdr& x)
378 // Read the header from the file.
379 if(!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)))
381 return false;
384 // The byte order of ELF header fields may not match that of the
385 // processor-specific data. The header fields are ordered to
386 // match the target execution environment, so we may need to
387 // memorize the order of all platforms based on the e_machine
388 // value. As a heuristic, if the type is invalid but its
389 // swapped value is okay then flip our swap mode.
390 ELF_Half et = x.e_type;
391 if(this->NeedSwap)
393 cmELFByteSwap(et);
395 if(!this->FileTypeValid(et))
397 cmELFByteSwap(et);
398 if(this->FileTypeValid(et))
400 // The previous byte order guess was wrong. Flip it.
401 this->NeedSwap = !this->NeedSwap;
405 // Fix the byte order of the header.
406 if(this->NeedSwap)
408 ByteSwap(x);
410 return true;
412 bool Read(ELF_Shdr& x)
414 if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
415 this->NeedSwap)
417 ByteSwap(x);
419 return this->Stream? true:false;
421 bool Read(ELF_Dyn& x)
423 if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
424 this->NeedSwap)
426 ByteSwap(x);
428 return this->Stream? true:false;
431 bool LoadSectionHeader(ELF_Half i)
433 // Read the section header from the file.
434 this->Stream.seekg(this->ELFHeader.e_shoff +
435 this->ELFHeader.e_shentsize * i);
436 if(!this->Read(this->SectionHeaders[i]))
438 return false;
441 // Identify some important sections.
442 if(this->SectionHeaders[i].sh_type == SHT_DYNAMIC)
444 this->DynamicSectionIndex = i;
446 return true;
449 bool LoadDynamicSection();
451 // Store the main ELF header.
452 ELF_Ehdr ELFHeader;
454 // Store all the section headers.
455 std::vector<ELF_Shdr> SectionHeaders;
457 // Store all entries of the DYNAMIC section.
458 std::vector<ELF_Dyn> DynamicSectionEntries;
461 //----------------------------------------------------------------------------
462 template <class Types>
463 cmELFInternalImpl<Types>
464 ::cmELFInternalImpl(cmELF* external,
465 cmsys::auto_ptr<std::ifstream>& fin,
466 ByteOrderType order):
467 cmELFInternal(external, fin, order)
469 // Read the main header.
470 if(!this->Read(this->ELFHeader))
472 this->SetErrorMessage("Failed to read main ELF header.");
473 return;
476 // Determine the ELF file type.
477 switch(this->ELFHeader.e_type)
479 case ET_NONE:
480 this->SetErrorMessage("ELF file type is NONE.");
481 return;
482 case ET_REL:
483 this->ELFType = cmELF::FileTypeRelocatableObject;
484 break;
485 case ET_EXEC:
486 this->ELFType = cmELF::FileTypeExecutable;
487 break;
488 case ET_DYN:
489 this->ELFType = cmELF::FileTypeSharedLibrary;
490 break;
491 case ET_CORE:
492 this->ELFType = cmELF::FileTypeCore;
493 break;
494 default:
496 unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
497 #if defined(ET_LOOS) && defined(ET_HIOS)
498 if(eti >= ET_LOOS && eti <= ET_HIOS)
500 this->ELFType = cmELF::FileTypeSpecificOS;
501 break;
503 #endif
504 #if defined(ET_LOPROC) && defined(ET_HIPROC)
505 if(eti >= ET_LOPROC && eti <= ET_HIPROC)
507 this->ELFType = cmELF::FileTypeSpecificProc;
508 break;
510 #endif
511 cmOStringStream e;
512 e << "Unknown ELF file type " << eti;
513 this->SetErrorMessage(e.str().c_str());
514 return;
518 // Load the section headers.
519 this->SectionHeaders.resize(this->ELFHeader.e_shnum);
520 for(ELF_Half i=0; i < this->ELFHeader.e_shnum; ++i)
522 if(!this->LoadSectionHeader(i))
524 this->SetErrorMessage("Failed to load section headers.");
525 return;
530 //----------------------------------------------------------------------------
531 template <class Types>
532 bool cmELFInternalImpl<Types>::LoadDynamicSection()
534 // If there is no dynamic section we are done.
535 if(this->DynamicSectionIndex < 0)
537 return false;
540 // If the section was already loaded we are done.
541 if(!this->DynamicSectionEntries.empty())
543 return true;
546 // Allocate the dynamic section entries.
547 ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
548 int n = sec.sh_size / sec.sh_entsize;
549 this->DynamicSectionEntries.resize(n);
551 // Read each entry.
552 for(int j=0; j < n; ++j)
554 // Seek to the beginning of the section entry.
555 this->Stream.seekg(sec.sh_offset + sec.sh_entsize*j);
556 ELF_Dyn& dyn = this->DynamicSectionEntries[j];
558 // Try reading the entry.
559 if(!this->Read(dyn))
561 this->SetErrorMessage("Error reading entry from DYNAMIC section.");
562 this->DynamicSectionIndex = -1;
563 return false;
566 return true;
569 //----------------------------------------------------------------------------
570 template <class Types>
571 unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount()
573 if(!this->LoadDynamicSection())
575 return 0;
577 for(unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i)
579 if(this->DynamicSectionEntries[i].d_tag == DT_NULL)
581 return i;
584 return this->DynamicSectionEntries.size();
587 //----------------------------------------------------------------------------
588 template <class Types>
589 unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
591 if(!this->LoadDynamicSection())
593 return 0;
595 if(j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size()))
597 return 0;
599 ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
600 return sec.sh_offset + sec.sh_entsize*j;
603 //----------------------------------------------------------------------------
604 template <class Types>
605 cmELF::StringEntry const*
606 cmELFInternalImpl<Types>::GetDynamicSectionString(int tag)
608 // Short-circuit if already checked.
609 std::map<int, StringEntry>::iterator dssi =
610 this->DynamicSectionStrings.find(tag);
611 if(dssi != this->DynamicSectionStrings.end())
613 if(dssi->second.Position > 0)
615 return &dssi->second;
617 return 0;
620 // Create an entry for this tag. Assume it is missing until found.
621 StringEntry& se = this->DynamicSectionStrings[tag];
622 se.Position = 0;
623 se.Size = 0;
624 se.IndexInSection = -1;
626 // Try reading the dynamic section.
627 if(!this->LoadDynamicSection())
629 return 0;
632 // Get the string table referenced by the DYNAMIC section.
633 ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
634 if(sec.sh_link >= this->SectionHeaders.size())
636 this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
637 return 0;
639 ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
641 // Look for the requested entry.
642 for(typename std::vector<ELF_Dyn>::iterator
643 di = this->DynamicSectionEntries.begin();
644 di != this->DynamicSectionEntries.end(); ++di)
646 ELF_Dyn& dyn = *di;
647 if(dyn.d_tag == tag)
649 // We found the tag requested.
650 // Make sure the position given is within the string section.
651 if(dyn.d_un.d_val >= strtab.sh_size)
653 this->SetErrorMessage("Section DYNAMIC references string beyond "
654 "the end of its string section.");
655 return 0;
658 // Seek to the position reported by the entry.
659 unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
660 unsigned long last = first;
661 unsigned long end = static_cast<unsigned long>(strtab.sh_size);
662 this->Stream.seekg(strtab.sh_offset + first);
664 // Read the string. It may be followed by more than one NULL
665 // terminator. Count the total size of the region allocated to
666 // the string. This assumes that the next string in the table
667 // is non-empty, but the "chrpath" tool makes the same
668 // assumption.
669 bool terminated = false;
670 char c;
671 while(last != end && this->Stream.get(c) && !(terminated && c))
673 ++last;
674 if(c)
676 se.Value += c;
678 else
680 terminated = true;
684 // Make sure the whole value was read.
685 if(!this->Stream)
687 this->SetErrorMessage("Dynamic section specifies unreadable RPATH.");
688 se.Value = "";
689 return 0;
692 // The value has been read successfully. Report it.
693 se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
694 se.Size = last - first;
695 se.IndexInSection = di - this->DynamicSectionEntries.begin();
696 return &se;
699 return 0;
702 //============================================================================
703 // External class implementation.
705 //----------------------------------------------------------------------------
706 cmELF::cmELF(const char* fname): Internal(0)
708 // Try to open the file.
709 cmsys::auto_ptr<std::ifstream> fin(new std::ifstream(fname));
711 // Quit now if the file could not be opened.
712 if(!fin.get() || !*fin)
714 this->ErrorMessage = "Error opening input file.";
715 return;
718 // Read the ELF identification block.
719 char ident[EI_NIDENT];
720 if(!fin->read(ident, EI_NIDENT))
722 this->ErrorMessage = "Error reading ELF identification.";
723 return;
725 if(!fin->seekg(0))
727 this->ErrorMessage = "Error seeking to beginning of file.";
728 return;
731 // Verify the ELF identification.
732 if(!(ident[EI_MAG0] == ELFMAG0 &&
733 ident[EI_MAG1] == ELFMAG1 &&
734 ident[EI_MAG2] == ELFMAG2 &&
735 ident[EI_MAG3] == ELFMAG3))
737 this->ErrorMessage = "File does not have a valid ELF identification.";
738 return;
741 // Check the byte order in which the rest of the file is encoded.
742 cmELFInternal::ByteOrderType order;
743 if(ident[EI_DATA] == ELFDATA2LSB)
745 // File is LSB.
746 order = cmELFInternal::ByteOrderLSB;
748 else if(ident[EI_DATA] == ELFDATA2MSB)
750 // File is MSB.
751 order = cmELFInternal::ByteOrderMSB;
753 else
755 this->ErrorMessage = "ELF file is not LSB or MSB encoded.";
756 return;
759 // Check the class of the file and construct the corresponding
760 // parser implementation.
761 if(ident[EI_CLASS] == ELFCLASS32)
763 // 32-bit ELF
764 this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
766 else if(ident[EI_CLASS] == ELFCLASS64)
768 // 64-bit ELF
769 this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
771 else
773 this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
774 return;
778 //----------------------------------------------------------------------------
779 cmELF::~cmELF()
781 delete this->Internal;
784 //----------------------------------------------------------------------------
785 bool cmELF::Valid() const
787 return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
790 //----------------------------------------------------------------------------
791 cmELF::FileType cmELF::GetFileType() const
793 if(this->Valid())
795 return this->Internal->GetFileType();
797 else
799 return FileTypeInvalid;
803 //----------------------------------------------------------------------------
804 unsigned int cmELF::GetNumberOfSections() const
806 if(this->Valid())
808 return this->Internal->GetNumberOfSections();
810 else
812 return 0;
816 //----------------------------------------------------------------------------
817 unsigned int cmELF::GetDynamicEntryCount() const
819 if(this->Valid())
821 return this->Internal->GetDynamicEntryCount();
823 else
825 return 0;
829 //----------------------------------------------------------------------------
830 unsigned long cmELF::GetDynamicEntryPosition(int index) const
832 if(this->Valid())
834 return this->Internal->GetDynamicEntryPosition(index);
836 else
838 return 0;
842 //----------------------------------------------------------------------------
843 bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const
845 if(this->Valid())
847 return this->Internal->ReadBytes(pos, size, buf);
849 else
851 return false;
855 //----------------------------------------------------------------------------
856 bool cmELF::GetSOName(std::string& soname)
858 if(StringEntry const* se = this->GetSOName())
860 soname = se->Value;
861 return true;
863 else
865 return false;
869 //----------------------------------------------------------------------------
870 cmELF::StringEntry const* cmELF::GetSOName()
872 if(this->Valid() &&
873 this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)
875 return this->Internal->GetSOName();
877 else
879 return 0;
883 //----------------------------------------------------------------------------
884 cmELF::StringEntry const* cmELF::GetRPath()
886 if(this->Valid() &&
887 (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
888 this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary))
890 return this->Internal->GetRPath();
892 else
894 return 0;
898 //----------------------------------------------------------------------------
899 cmELF::StringEntry const* cmELF::GetRunPath()
901 if(this->Valid() &&
902 (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
903 this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary))
905 return this->Internal->GetRunPath();
907 else
909 return 0;
913 //----------------------------------------------------------------------------
914 void cmELF::PrintInfo(std::ostream& os) const
916 if(this->Valid())
918 this->Internal->PrintInfo(os);
920 else
922 os << "Not a valid ELF file.\n";