diff options
Diffstat (limited to 'Source/cmELF.cxx')
-rw-r--r-- | Source/cmELF.cxx | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx new file mode 100644 index 0000000..1158fc0 --- /dev/null +++ b/Source/cmELF.cxx @@ -0,0 +1,920 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmStandardIncludes.h" // to get CMAKE_USE_ELF_PARSER first +#include "cmELF.h" + +#include <cmsys/auto_ptr.hxx> + +// Need the native byte order of the running CPU. +#define cmsys_CPU_UNKNOWN_OKAY // We can decide at runtime if not known. +#include <cmsys/CPU.h> + +// Include the ELF format information system header. +#include <elf.h> +#if defined(__sun) +# include <sys/link.h> // For dynamic section information +#endif + +//---------------------------------------------------------------------------- +// Low-level byte swapping implementation. +template <size_t s> struct cmELFByteSwapSize {}; +void cmELFByteSwap(char*, cmELFByteSwapSize<1> const&) +{ +} +void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const&) +{ + char one_byte; + one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; +} +void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const&) +{ + char one_byte; + one_byte = data[0]; data[0] = data[3]; data[3] = one_byte; + one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; +} +void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const&) +{ + char one_byte; + one_byte = data[0]; data[0] = data[7]; data[7] = one_byte; + one_byte = data[1]; data[1] = data[6]; data[6] = one_byte; + one_byte = data[2]; data[2] = data[5]; data[5] = one_byte; + one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; +} + +// Low-level byte swapping interface. +template <typename T> +void cmELFByteSwap(T& x) +{ + cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>()); +} + +//---------------------------------------------------------------------------- +class cmELFInternal +{ +public: + typedef cmELF::StringEntry StringEntry; + enum ByteOrderType { ByteOrderMSB, ByteOrderLSB }; + + // Construct and take ownership of the file stream object. + cmELFInternal(cmELF* external, + cmsys::auto_ptr<std::ifstream>& fin, + ByteOrderType order): + External(external), + Stream(*fin.release()), + ByteOrder(order), + ELFType(cmELF::FileTypeInvalid) + { + // In most cases the processor-specific byte order will match that + // of the target execution environment. If we choose wrong here + // it is fixed when the header is read. +#if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE + this->NeedSwap = (this->ByteOrder == ByteOrderMSB); +#elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG + this->NeedSwap = (this->ByteOrder == ByteOrderLSB); +#else + this->NeedSwap = false; // Final decision is at runtime anyway. +#endif + + // We have not yet loaded the section info. + this->DynamicSectionIndex = -1; + } + + // Destruct and delete the file stream object. + virtual ~cmELFInternal() + { + delete &this->Stream; + } + + // Forward to the per-class implementation. + virtual unsigned int GetNumberOfSections() const = 0; + virtual unsigned int GetDynamicEntryCount() = 0; + virtual unsigned long GetDynamicEntryPosition(int j) = 0; + virtual StringEntry const* GetDynamicSectionString(int tag) = 0; + virtual void PrintInfo(std::ostream& os) const = 0; + + bool ReadBytes(unsigned long pos, unsigned long size, char* buf) + { + this->Stream.seekg(pos); + this->Stream.read(buf, size); + return this->Stream?true:false; + } + + // Lookup the SONAME in the DYNAMIC section. + StringEntry const* GetSOName() + { + return this->GetDynamicSectionString(DT_SONAME); + } + + // Lookup the RPATH in the DYNAMIC section. + StringEntry const* GetRPath() + { + return this->GetDynamicSectionString(DT_RPATH); + } + + // Lookup the RUNPATH in the DYNAMIC section. + StringEntry const* GetRunPath() + { +#if defined(DT_RUNPATH) + return this->GetDynamicSectionString(DT_RUNPATH); +#else + return 0; +#endif + } + + // Return the recorded ELF type. + cmELF::FileType GetFileType() const { return this->ELFType; } +protected: + // Data common to all ELF class implementations. + + // The external cmELF object. + cmELF* External; + + // The stream from which to read. + std::istream& Stream; + + // The byte order of the ELF file. + ByteOrderType ByteOrder; + + // The ELF file type. + cmELF::FileType ELFType; + + // Whether we need to byte-swap structures read from the stream. + bool NeedSwap; + + // The section header index of the DYNAMIC section (-1 if none). + int DynamicSectionIndex; + + // Helper methods for subclasses. + void SetErrorMessage(const char* msg) + { + this->External->ErrorMessage = msg; + this->ELFType = cmELF::FileTypeInvalid; + } + + // Store string table entry states. + std::map<int, StringEntry> DynamicSectionStrings; +}; + +//---------------------------------------------------------------------------- +// Configure the implementation template for 32-bit ELF files. +struct cmELFTypes32 +{ + typedef Elf32_Ehdr ELF_Ehdr; + typedef Elf32_Shdr ELF_Shdr; + typedef Elf32_Dyn ELF_Dyn; + typedef Elf32_Half ELF_Half; + static const char* GetName() { return "32-bit"; } +}; + +// Configure the implementation template for 32-bit ELF files. +struct cmELFTypes64 +{ + typedef Elf64_Ehdr ELF_Ehdr; + typedef Elf64_Shdr ELF_Shdr; + typedef Elf64_Dyn ELF_Dyn; + typedef Elf64_Half ELF_Half; + static const char* GetName() { return "64-bit"; } +}; + +//---------------------------------------------------------------------------- +// Parser implementation template. +template <class Types> +class cmELFInternalImpl: public cmELFInternal +{ +public: + // Copy the ELF file format types from our configuration parameter. + typedef typename Types::ELF_Ehdr ELF_Ehdr; + typedef typename Types::ELF_Shdr ELF_Shdr; + typedef typename Types::ELF_Dyn ELF_Dyn; + typedef typename Types::ELF_Half ELF_Half; + + // Construct with a stream and byte swap indicator. + cmELFInternalImpl(cmELF* external, + cmsys::auto_ptr<std::ifstream>& fin, + ByteOrderType order); + + // Return the number of sections as specified by the ELF header. + virtual unsigned int GetNumberOfSections() const + { + return static_cast<unsigned int>(this->ELFHeader.e_shnum); + } + + // Get the file position and size of a dynamic section entry. + virtual unsigned int GetDynamicEntryCount(); + virtual unsigned long GetDynamicEntryPosition(int j); + + // Lookup a string from the dynamic section with the given tag. + virtual StringEntry const* GetDynamicSectionString(int tag); + + // Print information about the ELF file. + virtual void PrintInfo(std::ostream& os) const + { + os << "ELF " << Types::GetName(); + if(this->ByteOrder == ByteOrderMSB) + { + os << " MSB"; + } + else if(this->ByteOrder == ByteOrderLSB) + { + os << " LSB"; + } + switch(this->ELFType) + { + case cmELF::FileTypeInvalid: + os << " invalid file"; + break; + case cmELF::FileTypeRelocatableObject: + os << " relocatable object"; + break; + case cmELF::FileTypeExecutable: + os << " executable"; + break; + case cmELF::FileTypeSharedLibrary: + os << " shared library"; + break; + case cmELF::FileTypeCore: + os << " core file"; + break; + case cmELF::FileTypeSpecificOS: + os << " os-specific type"; + break; + case cmELF::FileTypeSpecificProc: + os << " processor-specific type"; + break; + } + os << "\n"; + } + +private: + void ByteSwap(ELF_Ehdr& elf_header) + { + cmELFByteSwap(elf_header.e_type); + cmELFByteSwap(elf_header.e_machine); + cmELFByteSwap(elf_header.e_version); + cmELFByteSwap(elf_header.e_entry); + cmELFByteSwap(elf_header.e_phoff); + cmELFByteSwap(elf_header.e_shoff); + cmELFByteSwap(elf_header.e_flags); + cmELFByteSwap(elf_header.e_ehsize); + cmELFByteSwap(elf_header.e_phentsize); + cmELFByteSwap(elf_header.e_phnum); + cmELFByteSwap(elf_header.e_shentsize); + cmELFByteSwap(elf_header.e_shnum); + cmELFByteSwap(elf_header.e_shstrndx); + } + + void ByteSwap(ELF_Shdr& sec_header) + { + cmELFByteSwap(sec_header.sh_name); + cmELFByteSwap(sec_header.sh_type); + cmELFByteSwap(sec_header.sh_flags); + cmELFByteSwap(sec_header.sh_addr); + cmELFByteSwap(sec_header.sh_offset); + cmELFByteSwap(sec_header.sh_size); + cmELFByteSwap(sec_header.sh_link); + cmELFByteSwap(sec_header.sh_info); + cmELFByteSwap(sec_header.sh_addralign); + cmELFByteSwap(sec_header.sh_entsize); + } + + void ByteSwap(ELF_Dyn& dyn) + { + cmELFByteSwap(dyn.d_tag); + switch (dyn.d_tag) + { + case DT_NULL: /* dyn.d_un ignored */ break; + case DT_NEEDED: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_PLTRELSZ: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_PLTGOT: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_HASH: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_STRTAB: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_SYMTAB: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_RELA: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_RELASZ: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_RELAENT: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_STRSZ: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_SYMENT: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_INIT: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_FINI: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_SONAME: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_RPATH: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_SYMBOLIC: /* dyn.d_un ignored */ break; + case DT_REL: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_RELSZ: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_RELENT: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_PLTREL: cmELFByteSwap(dyn.d_un.d_val); break; + case DT_DEBUG: cmELFByteSwap(dyn.d_un.d_ptr); break; + case DT_TEXTREL: /* dyn.d_un ignored */ break; + case DT_JMPREL: cmELFByteSwap(dyn.d_un.d_ptr); break; +#ifdef T_BIND_NOW + case T_BIND_NOW: /* dyn.d_un ignored */ break; +#endif +#ifdef DT_INIT_ARRAY + case DT_INIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break; +#endif +#ifdef DT_FINI_ARRAY + case DT_FINI_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break; +#endif +#ifdef DT_INIT_ARRAYSZ + case DT_INIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break; +#endif +#ifdef DT_FINI_ARRAYSZ + case DT_FINI_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break; +#endif +#ifdef DT_RUNPATH + case DT_RUNPATH: cmELFByteSwap(dyn.d_un.d_val); break; +#endif +#ifdef DT_FLAGS + case DT_FLAGS: cmELFByteSwap(dyn.d_un.d_val); break; +#endif +#ifdef DT_PREINIT_ARRAY + case DT_PREINIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break; +#endif +#ifdef DT_PREINIT_ARRAYSZ + case DT_PREINIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break; +#endif + } + } + + bool FileTypeValid(ELF_Half et) + { + unsigned int eti = static_cast<unsigned int>(et); + if(eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || + eti == ET_DYN || eti == ET_CORE) + { + return true; + } +#if defined(ET_LOOS) && defined(ET_HIOS) + if(eti >= ET_LOOS && eti <= ET_HIOS) + { + return true; + } +#endif +#if defined(ET_LOPROC) && defined(ET_HIPROC) + if(eti >= ET_LOPROC && eti <= ET_HIPROC) + { + return true; + } +#endif + return false; + } + + bool Read(ELF_Ehdr& x) + { + // Read the header from the file. + if(!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x))) + { + return false; + } + + // The byte order of ELF header fields may not match that of the + // processor-specific data. The header fields are ordered to + // match the target execution environment, so we may need to + // memorize the order of all platforms based on the e_machine + // value. As a heuristic, if the type is invalid but its + // swapped value is okay then flip our swap mode. + ELF_Half et = x.e_type; + if(this->NeedSwap) + { + cmELFByteSwap(et); + } + if(!this->FileTypeValid(et)) + { + cmELFByteSwap(et); + if(this->FileTypeValid(et)) + { + // The previous byte order guess was wrong. Flip it. + this->NeedSwap = !this->NeedSwap; + } + } + + // Fix the byte order of the header. + if(this->NeedSwap) + { + ByteSwap(x); + } + return true; + } + bool Read(ELF_Shdr& x) + { + if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) && + this->NeedSwap) + { + ByteSwap(x); + } + return this->Stream? true:false; + } + bool Read(ELF_Dyn& x) + { + if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) && + this->NeedSwap) + { + ByteSwap(x); + } + return this->Stream? true:false; + } + + bool LoadSectionHeader(ELF_Half i) + { + // Read the section header from the file. + this->Stream.seekg(this->ELFHeader.e_shoff + + this->ELFHeader.e_shentsize * i); + if(!this->Read(this->SectionHeaders[i])) + { + return false; + } + + // Identify some important sections. + if(this->SectionHeaders[i].sh_type == SHT_DYNAMIC) + { + this->DynamicSectionIndex = i; + } + return true; + } + + bool LoadDynamicSection(); + + // Store the main ELF header. + ELF_Ehdr ELFHeader; + + // Store all the section headers. + std::vector<ELF_Shdr> SectionHeaders; + + // Store all entries of the DYNAMIC section. + std::vector<ELF_Dyn> DynamicSectionEntries; +}; + +//---------------------------------------------------------------------------- +template <class Types> +cmELFInternalImpl<Types> +::cmELFInternalImpl(cmELF* external, + cmsys::auto_ptr<std::ifstream>& fin, + ByteOrderType order): + cmELFInternal(external, fin, order) +{ + // Read the main header. + if(!this->Read(this->ELFHeader)) + { + this->SetErrorMessage("Failed to read main ELF header."); + return; + } + + // Determine the ELF file type. + switch(this->ELFHeader.e_type) + { + case ET_NONE: + this->SetErrorMessage("ELF file type is NONE."); + return; + case ET_REL: + this->ELFType = cmELF::FileTypeRelocatableObject; + break; + case ET_EXEC: + this->ELFType = cmELF::FileTypeExecutable; + break; + case ET_DYN: + this->ELFType = cmELF::FileTypeSharedLibrary; + break; + case ET_CORE: + this->ELFType = cmELF::FileTypeCore; + break; + default: + { + unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); +#if defined(ET_LOOS) && defined(ET_HIOS) + if(eti >= ET_LOOS && eti <= ET_HIOS) + { + this->ELFType = cmELF::FileTypeSpecificOS; + break; + } +#endif +#if defined(ET_LOPROC) && defined(ET_HIPROC) + if(eti >= ET_LOPROC && eti <= ET_HIPROC) + { + this->ELFType = cmELF::FileTypeSpecificProc; + break; + } +#endif + cmOStringStream e; + e << "Unknown ELF file type " << eti; + this->SetErrorMessage(e.str().c_str()); + return; + } + } + + // Load the section headers. + this->SectionHeaders.resize(this->ELFHeader.e_shnum); + for(ELF_Half i=0; i < this->ELFHeader.e_shnum; ++i) + { + if(!this->LoadSectionHeader(i)) + { + this->SetErrorMessage("Failed to load section headers."); + return; + } + } +} + +//---------------------------------------------------------------------------- +template <class Types> +bool cmELFInternalImpl<Types>::LoadDynamicSection() +{ + // If there is no dynamic section we are done. + if(this->DynamicSectionIndex < 0) + { + return false; + } + + // If the section was already loaded we are done. + if(!this->DynamicSectionEntries.empty()) + { + return true; + } + + // Allocate the dynamic section entries. + ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; + int n = static_cast<int>(sec.sh_size / sec.sh_entsize); + this->DynamicSectionEntries.resize(n); + + // Read each entry. + for(int j=0; j < n; ++j) + { + // Seek to the beginning of the section entry. + this->Stream.seekg(sec.sh_offset + sec.sh_entsize*j); + ELF_Dyn& dyn = this->DynamicSectionEntries[j]; + + // Try reading the entry. + if(!this->Read(dyn)) + { + this->SetErrorMessage("Error reading entry from DYNAMIC section."); + this->DynamicSectionIndex = -1; + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +template <class Types> +unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount() +{ + if(!this->LoadDynamicSection()) + { + return 0; + } + for(unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i) + { + if(this->DynamicSectionEntries[i].d_tag == DT_NULL) + { + return i; + } + } + return static_cast<unsigned int>(this->DynamicSectionEntries.size()); +} + +//---------------------------------------------------------------------------- +template <class Types> +unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j) +{ + if(!this->LoadDynamicSection()) + { + return 0; + } + if(j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) + { + return 0; + } + ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; + return static_cast<unsigned long>(sec.sh_offset + sec.sh_entsize*j); +} + +//---------------------------------------------------------------------------- +template <class Types> +cmELF::StringEntry const* +cmELFInternalImpl<Types>::GetDynamicSectionString(int tag) +{ + // Short-circuit if already checked. + std::map<int, StringEntry>::iterator dssi = + this->DynamicSectionStrings.find(tag); + if(dssi != this->DynamicSectionStrings.end()) + { + if(dssi->second.Position > 0) + { + return &dssi->second; + } + return 0; + } + + // Create an entry for this tag. Assume it is missing until found. + StringEntry& se = this->DynamicSectionStrings[tag]; + se.Position = 0; + se.Size = 0; + se.IndexInSection = -1; + + // Try reading the dynamic section. + if(!this->LoadDynamicSection()) + { + return 0; + } + + // Get the string table referenced by the DYNAMIC section. + ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; + if(sec.sh_link >= this->SectionHeaders.size()) + { + this->SetErrorMessage("Section DYNAMIC has invalid string table index."); + return 0; + } + ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link]; + + // Look for the requested entry. + for(typename std::vector<ELF_Dyn>::iterator + di = this->DynamicSectionEntries.begin(); + di != this->DynamicSectionEntries.end(); ++di) + { + ELF_Dyn& dyn = *di; + if(dyn.d_tag == tag) + { + // We found the tag requested. + // Make sure the position given is within the string section. + if(dyn.d_un.d_val >= strtab.sh_size) + { + this->SetErrorMessage("Section DYNAMIC references string beyond " + "the end of its string section."); + return 0; + } + + // Seek to the position reported by the entry. + unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val); + unsigned long last = first; + unsigned long end = static_cast<unsigned long>(strtab.sh_size); + this->Stream.seekg(strtab.sh_offset + first); + + // Read the string. It may be followed by more than one NULL + // terminator. Count the total size of the region allocated to + // the string. This assumes that the next string in the table + // is non-empty, but the "chrpath" tool makes the same + // assumption. + bool terminated = false; + char c; + while(last != end && this->Stream.get(c) && !(terminated && c)) + { + ++last; + if(c) + { + se.Value += c; + } + else + { + terminated = true; + } + } + + // Make sure the whole value was read. + if(!this->Stream) + { + this->SetErrorMessage("Dynamic section specifies unreadable RPATH."); + se.Value = ""; + return 0; + } + + // The value has been read successfully. Report it. + se.Position = static_cast<unsigned long>(strtab.sh_offset + first); + se.Size = last - first; + se.IndexInSection = + static_cast<int>(di - this->DynamicSectionEntries.begin()); + return &se; + } + } + return 0; +} + +//============================================================================ +// External class implementation. + +//---------------------------------------------------------------------------- +cmELF::cmELF(const char* fname): Internal(0) +{ + // Try to open the file. + cmsys::auto_ptr<std::ifstream> fin(new std::ifstream(fname)); + + // Quit now if the file could not be opened. + if(!fin.get() || !*fin) + { + this->ErrorMessage = "Error opening input file."; + return; + } + + // Read the ELF identification block. + char ident[EI_NIDENT]; + if(!fin->read(ident, EI_NIDENT)) + { + this->ErrorMessage = "Error reading ELF identification."; + return; + } + if(!fin->seekg(0)) + { + this->ErrorMessage = "Error seeking to beginning of file."; + return; + } + + // Verify the ELF identification. + if(!(ident[EI_MAG0] == ELFMAG0 && + ident[EI_MAG1] == ELFMAG1 && + ident[EI_MAG2] == ELFMAG2 && + ident[EI_MAG3] == ELFMAG3)) + { + this->ErrorMessage = "File does not have a valid ELF identification."; + return; + } + + // Check the byte order in which the rest of the file is encoded. + cmELFInternal::ByteOrderType order; + if(ident[EI_DATA] == ELFDATA2LSB) + { + // File is LSB. + order = cmELFInternal::ByteOrderLSB; + } + else if(ident[EI_DATA] == ELFDATA2MSB) + { + // File is MSB. + order = cmELFInternal::ByteOrderMSB; + } + else + { + this->ErrorMessage = "ELF file is not LSB or MSB encoded."; + return; + } + + // Check the class of the file and construct the corresponding + // parser implementation. + if(ident[EI_CLASS] == ELFCLASS32) + { + // 32-bit ELF + this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order); + } + else if(ident[EI_CLASS] == ELFCLASS64) + { + // 64-bit ELF + this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order); + } + else + { + this->ErrorMessage = "ELF file class is not 32-bit or 64-bit."; + return; + } +} + +//---------------------------------------------------------------------------- +cmELF::~cmELF() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +bool cmELF::Valid() const +{ + return this->Internal && this->Internal->GetFileType() != FileTypeInvalid; +} + +//---------------------------------------------------------------------------- +cmELF::FileType cmELF::GetFileType() const +{ + if(this->Valid()) + { + return this->Internal->GetFileType(); + } + else + { + return FileTypeInvalid; + } +} + +//---------------------------------------------------------------------------- +unsigned int cmELF::GetNumberOfSections() const +{ + if(this->Valid()) + { + return this->Internal->GetNumberOfSections(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +unsigned int cmELF::GetDynamicEntryCount() const +{ + if(this->Valid()) + { + return this->Internal->GetDynamicEntryCount(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +unsigned long cmELF::GetDynamicEntryPosition(int index) const +{ + if(this->Valid()) + { + return this->Internal->GetDynamicEntryPosition(index); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const +{ + if(this->Valid()) + { + return this->Internal->ReadBytes(pos, size, buf); + } + else + { + return false; + } +} + +//---------------------------------------------------------------------------- +bool cmELF::GetSOName(std::string& soname) +{ + if(StringEntry const* se = this->GetSOName()) + { + soname = se->Value; + return true; + } + else + { + return false; + } +} + +//---------------------------------------------------------------------------- +cmELF::StringEntry const* cmELF::GetSOName() +{ + if(this->Valid() && + this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) + { + return this->Internal->GetSOName(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +cmELF::StringEntry const* cmELF::GetRPath() +{ + if(this->Valid() && + (this->Internal->GetFileType() == cmELF::FileTypeExecutable || + this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) + { + return this->Internal->GetRPath(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +cmELF::StringEntry const* cmELF::GetRunPath() +{ + if(this->Valid() && + (this->Internal->GetFileType() == cmELF::FileTypeExecutable || + this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) + { + return this->Internal->GetRunPath(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +void cmELF::PrintInfo(std::ostream& os) const +{ + if(this->Valid()) + { + this->Internal->PrintInfo(os); + } + else + { + os << "Not a valid ELF file.\n"; + } +} |