| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmELF.h"
 
- #include "cmAlgorithms.h"
 
- #include "cm_kwiml.h"
 
- #include "cmsys/FStream.hxx"
 
- #include <map>
 
- #include <memory> // IWYU pragma: keep
 
- #include <sstream>
 
- #include <stddef.h>
 
- #include <utility>
 
- #include <vector>
 
- // Include the ELF format information system header.
 
- #if defined(__OpenBSD__)
 
- #  include <elf_abi.h>
 
- #  include <stdint.h>
 
- #elif defined(__HAIKU__)
 
- #  include <elf32.h>
 
- #  include <elf64.h>
 
- typedef struct Elf32_Ehdr Elf32_Ehdr;
 
- typedef struct Elf32_Shdr Elf32_Shdr;
 
- typedef struct Elf32_Sym Elf32_Sym;
 
- typedef struct Elf32_Rel Elf32_Rel;
 
- typedef struct Elf32_Rela Elf32_Rela;
 
- #  define ELFMAG0 0x7F
 
- #  define ELFMAG1 'E'
 
- #  define ELFMAG2 'L'
 
- #  define ELFMAG3 'F'
 
- #  define ET_NONE 0
 
- #  define ET_REL 1
 
- #  define ET_EXEC 2
 
- #  define ET_DYN 3
 
- #  define ET_CORE 4
 
- #  define EM_386 3
 
- #  define EM_SPARC 2
 
- #  define EM_PPC 20
 
- #else
 
- #  include <elf.h>
 
- #endif
 
- #if defined(__sun)
 
- #  include <sys/link.h> // For dynamic section information
 
- #endif
 
- #ifdef _SCO_DS
 
- #  include <link.h> // For DT_SONAME etc.
 
- #endif
 
- #ifndef DT_RUNPATH
 
- #  define DT_RUNPATH 29
 
- #endif
 
- // Low-level byte swapping implementation.
 
- template <size_t s>
 
- struct cmELFByteSwapSize
 
- {
 
- };
 
- void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> /*unused*/)
 
- {
 
- }
 
- void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/)
 
- {
 
-   char one_byte;
 
-   one_byte = data[0];
 
-   data[0] = data[1];
 
-   data[1] = one_byte;
 
- }
 
- void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
 
- {
 
-   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> /*unused*/)
 
- {
 
-   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, std::unique_ptr<cmsys::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 KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
 
-     this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
 
- #elif KWIML_ABI_ENDIAN_ID == KWIML_ABI_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 long GetDynamicEntryPosition(int j) = 0;
 
-   virtual cmELF::DynamicEntryList GetDynamicEntries() = 0;
 
-   virtual std::vector<char> EncodeDynamicEntries(
 
-     const cmELF::DynamicEntryList&) = 0;
 
-   virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0;
 
-   virtual void PrintInfo(std::ostream& os) const = 0;
 
-   // 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()
 
-   {
 
-     return this->GetDynamicSectionString(DT_RUNPATH);
 
-   }
 
-   // 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<unsigned 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;
 
-   typedef KWIML_INT_uint32_t tagtype;
 
-   static const char* GetName() { return "32-bit"; }
 
- };
 
- // Configure the implementation template for 64-bit ELF files.
 
- #ifndef _SCO_DS
 
- struct cmELFTypes64
 
- {
 
-   typedef Elf64_Ehdr ELF_Ehdr;
 
-   typedef Elf64_Shdr ELF_Shdr;
 
-   typedef Elf64_Dyn ELF_Dyn;
 
-   typedef Elf64_Half ELF_Half;
 
-   typedef KWIML_INT_uint64_t tagtype;
 
-   static const char* GetName() { return "64-bit"; }
 
- };
 
- #endif
 
- // 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;
 
-   typedef typename Types::tagtype tagtype;
 
-   // Construct with a stream and byte swap indicator.
 
-   cmELFInternalImpl(cmELF* external, std::unique_ptr<cmsys::ifstream>& fin,
 
-                     ByteOrderType order);
 
-   // Return the number of sections as specified by the ELF header.
 
-   unsigned int GetNumberOfSections() const override
 
-   {
 
-     return static_cast<unsigned int>(this->ELFHeader.e_shnum);
 
-   }
 
-   // Get the file position of a dynamic section entry.
 
-   unsigned long GetDynamicEntryPosition(int j) override;
 
-   cmELF::DynamicEntryList GetDynamicEntries() override;
 
-   std::vector<char> EncodeDynamicEntries(
 
-     const cmELF::DynamicEntryList&) override;
 
-   // Lookup a string from the dynamic section with the given tag.
 
-   StringEntry const* GetDynamicSectionString(unsigned int tag) override;
 
-   // Print information about the ELF file.
 
-   void PrintInfo(std::ostream& os) const override
 
-   {
 
-     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:
 
-   // ByteSwap(ELF_Dyn) assumes d_val and d_ptr are the same size
 
-   typedef char dyn_size_assert
 
-     [sizeof(ELF_Dyn().d_un.d_val) == sizeof(ELF_Dyn().d_un.d_ptr) ? 1 : -1];
 
-   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);
 
-     cmELFByteSwap(dyn.d_un.d_val);
 
-   }
 
-   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.fail();
 
-   }
 
-   bool Read(ELF_Dyn& x)
 
-   {
 
-     if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
 
-         this->NeedSwap) {
 
-       ByteSwap(x);
 
-     }
 
-     return !this->Stream.fail();
 
-   }
 
-   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, std::unique_ptr<cmsys::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
 
-       std::ostringstream 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;
 
-   }
 
-   // If there are no entries we are done.
 
-   ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
 
-   if (sec.sh_entsize == 0) {
 
-     return false;
 
-   }
 
-   // Allocate the dynamic section entries.
 
-   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 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::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries()
 
- {
 
-   cmELF::DynamicEntryList result;
 
-   // Ensure entries have been read from file
 
-   if (!this->LoadDynamicSection()) {
 
-     return result;
 
-   }
 
-   // Copy into public array
 
-   result.reserve(this->DynamicSectionEntries.size());
 
-   for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
 
-     result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
 
-   }
 
-   return result;
 
- }
 
- template <class Types>
 
- std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
 
-   const cmELF::DynamicEntryList& entries)
 
- {
 
-   std::vector<char> result;
 
-   result.reserve(sizeof(ELF_Dyn) * entries.size());
 
-   for (auto const& entry : entries) {
 
-     // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars
 
-     ELF_Dyn dyn;
 
-     dyn.d_tag = static_cast<tagtype>(entry.first);
 
-     dyn.d_un.d_val = static_cast<tagtype>(entry.second);
 
-     if (this->NeedSwap) {
 
-       ByteSwap(dyn);
 
-     }
 
-     char* pdyn = reinterpret_cast<char*>(&dyn);
 
-     cmAppend(result, pdyn, pdyn + sizeof(ELF_Dyn));
 
-   }
 
-   return result;
 
- }
 
- template <class Types>
 
- cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
 
-   unsigned int tag)
 
- {
 
-   // Short-circuit if already checked.
 
-   std::map<unsigned int, StringEntry>::iterator dssi =
 
-     this->DynamicSectionStrings.find(tag);
 
-   if (dssi != this->DynamicSectionStrings.end()) {
 
-     if (dssi->second.Position > 0) {
 
-       return &dssi->second;
 
-     }
 
-     return nullptr;
 
-   }
 
-   // 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 nullptr;
 
-   }
 
-   // 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 nullptr;
 
-   }
 
-   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 (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(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 nullptr;
 
-       }
 
-       // 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 nullptr;
 
-       }
 
-       // 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 nullptr;
 
- }
 
- //============================================================================
 
- // External class implementation.
 
- const long cmELF::TagRPath = DT_RPATH;
 
- const long cmELF::TagRunPath = DT_RUNPATH;
 
- #ifdef DT_MIPS_RLD_MAP_REL
 
- const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL;
 
- #else
 
- const long cmELF::TagMipsRldMapRel = 0;
 
- #endif
 
- cmELF::cmELF(const char* fname)
 
-   : Internal(nullptr)
 
- {
 
-   // Try to open the file.
 
-   std::unique_ptr<cmsys::ifstream> fin(new cmsys::ifstream(fname));
 
-   // Quit now if the file could not be opened.
 
-   if (!fin || !*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);
 
-   }
 
- #ifndef _SCO_DS
 
-   else if (ident[EI_CLASS] == ELFCLASS64) {
 
-     // 64-bit ELF
 
-     this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
 
-   }
 
- #endif
 
-   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();
 
-   }
 
-   return FileTypeInvalid;
 
- }
 
- unsigned int cmELF::GetNumberOfSections() const
 
- {
 
-   if (this->Valid()) {
 
-     return this->Internal->GetNumberOfSections();
 
-   }
 
-   return 0;
 
- }
 
- unsigned long cmELF::GetDynamicEntryPosition(int index) const
 
- {
 
-   if (this->Valid()) {
 
-     return this->Internal->GetDynamicEntryPosition(index);
 
-   }
 
-   return 0;
 
- }
 
- cmELF::DynamicEntryList cmELF::GetDynamicEntries() const
 
- {
 
-   if (this->Valid()) {
 
-     return this->Internal->GetDynamicEntries();
 
-   }
 
-   return cmELF::DynamicEntryList();
 
- }
 
- std::vector<char> cmELF::EncodeDynamicEntries(
 
-   const cmELF::DynamicEntryList& dentries) const
 
- {
 
-   if (this->Valid()) {
 
-     return this->Internal->EncodeDynamicEntries(dentries);
 
-   }
 
-   return std::vector<char>();
 
- }
 
- bool cmELF::GetSOName(std::string& soname)
 
- {
 
-   if (StringEntry const* se = this->GetSOName()) {
 
-     soname = se->Value;
 
-     return true;
 
-   }
 
-   return false;
 
- }
 
- cmELF::StringEntry const* cmELF::GetSOName()
 
- {
 
-   if (this->Valid() &&
 
-       this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) {
 
-     return this->Internal->GetSOName();
 
-   }
 
-   return nullptr;
 
- }
 
- cmELF::StringEntry const* cmELF::GetRPath()
 
- {
 
-   if (this->Valid() &&
 
-       (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
 
-        this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
 
-     return this->Internal->GetRPath();
 
-   }
 
-   return nullptr;
 
- }
 
- cmELF::StringEntry const* cmELF::GetRunPath()
 
- {
 
-   if (this->Valid() &&
 
-       (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
 
-        this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
 
-     return this->Internal->GetRunPath();
 
-   }
 
-   return nullptr;
 
- }
 
- void cmELF::PrintInfo(std::ostream& os) const
 
- {
 
-   if (this->Valid()) {
 
-     this->Internal->PrintInfo(os);
 
-   } else {
 
-     os << "Not a valid ELF file.\n";
 
-   }
 
- }
 
 
  |