diff options
author | Brad King <brad.king@kitware.com> | 2008-02-29 16:12:59 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2008-02-29 16:12:59 (GMT) |
commit | 03ef00bc93511b6909f022a143c93bbb29bc2c58 (patch) | |
tree | a18a77f9eca43242a1fc2209156aa110bfb34443 | |
parent | 44f696f8dae9a30cb69590954705511631153473 (diff) | |
download | CMake-03ef00bc93511b6909f022a143c93bbb29bc2c58.zip CMake-03ef00bc93511b6909f022a143c93bbb29bc2c58.tar.gz CMake-03ef00bc93511b6909f022a143c93bbb29bc2c58.tar.bz2 |
ENH: Make cmELF parser more general and powerful
- Add support to get RPATH and RUNPATH entries.
- Add support to get file offsets to strings.
- Add more DT_* tags to byte swapping.
-rw-r--r-- | Source/cmELF.cxx | 163 | ||||
-rw-r--r-- | Source/cmELF.h | 17 |
2 files changed, 152 insertions, 28 deletions
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 5450eea..09a7e17 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -65,6 +65,7 @@ void cmELFByteSwap(T& x) class cmELFInternal { public: + typedef cmELF::StringEntry StringEntry; enum ByteOrderType { ByteOrderMSB, ByteOrderLSB }; // Construct and take ownership of the file stream object. @@ -95,9 +96,31 @@ public: // Forward to the per-class implementation. virtual unsigned int GetNumberOfSections() const = 0; - virtual bool GetSOName(std::string& soname) = 0; + virtual StringEntry const* GetDynamicSectionString(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() + { +#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: @@ -127,6 +150,9 @@ protected: this->External->ErrorMessage = msg; this->ELFType = cmELF::FileTypeInvalid; } + + // Store string table entry states. + std::map<int, StringEntry> DynamicSectionStrings; }; //---------------------------------------------------------------------------- @@ -173,8 +199,8 @@ public: return static_cast<unsigned int>(this->ELFHeader.e_shnum); } - // Lookup the SONAME in the DYNAMIC section. - virtual bool GetSOName(std::string& soname); + // 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 @@ -270,6 +296,33 @@ private: 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 } } @@ -329,10 +382,6 @@ private: // Store all entries of the DYNAMIC section. std::vector<ELF_Dyn> DynamicSectionEntries; - - // Store the SOName if it has been loaded. - std::string SOName; - bool SONameChecked; }; //---------------------------------------------------------------------------- @@ -343,9 +392,6 @@ cmELFInternalImpl<Types> ByteOrderType order): cmELFInternal(external, fin, order) { - // Initialize state. - this->SONameChecked = false; - // Read the main header. if(!this->Read(this->ELFHeader)) { @@ -424,20 +470,29 @@ bool cmELFInternalImpl<Types>::LoadDynamicSection() //---------------------------------------------------------------------------- template <class Types> -bool cmELFInternalImpl<Types>::GetSOName(std::string& soname) +cmELF::StringEntry const* +cmELFInternalImpl<Types>::GetDynamicSectionString(int tag) { // Short-circuit if already checked. - if(this->SONameChecked) + std::map<int, StringEntry>::iterator dssi = + this->DynamicSectionStrings.find(tag); + if(dssi != this->DynamicSectionStrings.end()) { - soname = this->SOName; - return !soname.empty(); + if(dssi->second.Position > 0) + { + return &dssi->second; + } + return 0; } - this->SONameChecked = true; + + // Create an entry for this tag. Assume it is missing until found. + StringEntry& se = this->DynamicSectionStrings[tag]; + se.Position = 0; // Try reading the dynamic section. if(!this->LoadDynamicSection()) { - return false; + return 0; } // Get the string table referenced by the DYNAMIC section. @@ -445,35 +500,43 @@ bool cmELFInternalImpl<Types>::GetSOName(std::string& soname) if(sec.sh_link >= this->SectionHeaders.size()) { this->SetErrorMessage("Section DYNAMIC has invalid string table index."); - return false; + return 0; } ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link]; - // Look for the soname entry. + // 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 == DT_SONAME) + if(dyn.d_tag == tag) { + // Seek to the position reported by the entry. this->Stream.seekg(strtab.sh_offset + dyn.d_un.d_val); + + // Read the string. char c; while(this->Stream.get(c) && c != 0) { - this->SOName += c; + se.Value += c; } + + // Make sure the whole value was read. if(!this->Stream) { - this->SetErrorMessage("Dynamic section specifies unreadable SONAME."); - this->SOName = ""; - return false; + this->SetErrorMessage("Dynamic section specifies unreadable RPATH."); + se.Value = ""; + return 0; } - soname = this->SOName; - return true; + + // The value has been read successfully. Report it. + se.Position = + static_cast<unsigned long>(strtab.sh_offset + dyn.d_un.d_val); + return &se; } } - return false; + return 0; } //============================================================================ @@ -593,14 +656,58 @@ unsigned int cmELF::GetNumberOfSections() const //---------------------------------------------------------------------------- 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(soname); + return this->Internal->GetSOName(); } else { - return false; + 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; } } diff --git a/Source/cmELF.h b/Source/cmELF.h index 11bf354..716b3d2 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -54,6 +54,16 @@ public: FileTypeCore }; + /** Represent string table entries. */ + struct StringEntry + { + // The string value itself. + std::string Value; + + // The position in the file at which the string appears. + unsigned long Position; + }; + /** Get the type of the file opened. */ FileType GetFileType() const; @@ -62,6 +72,13 @@ public: /** Get the SONAME field if any. */ bool GetSOName(std::string& soname); + StringEntry const* GetSOName(); + + /** Get the RPATH field if any. */ + StringEntry const* GetRPath(); + + /** Get the RUNPATH field if any. */ + StringEntry const* GetRunPath(); /** Print human-readable information about the ELF file. */ void PrintInfo(std::ostream& os) const; |