[cmake-commits] king committed cmELF.cxx 1.3 1.4 cmELF.h 1.1 1.2

cmake-commits at cmake.org cmake-commits at cmake.org
Fri Feb 29 11:13:01 EST 2008


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv7316/Source

Modified Files:
	cmELF.cxx cmELF.h 
Log Message:
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.


Index: cmELF.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmELF.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cmELF.h	27 Feb 2008 21:26:35 -0000	1.1
+++ cmELF.h	29 Feb 2008 16:12:59 -0000	1.2
@@ -54,6 +54,16 @@
     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 @@
 
   /** 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;

Index: cmELF.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmELF.cxx,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmELF.cxx	28 Feb 2008 13:43:10 -0000	1.3
+++ cmELF.cxx	29 Feb 2008 16:12:59 -0000	1.4
@@ -65,6 +65,7 @@
 class cmELFInternal
 {
 public:
+  typedef cmELF::StringEntry StringEntry;
   enum ByteOrderType { ByteOrderMSB, ByteOrderLSB };
 
   // Construct and take ownership of the file stream object.
@@ -95,9 +96,31 @@
 
   // 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 @@
     this->External->ErrorMessage = msg;
     this->ELFType = cmELF::FileTypeInvalid;
     }
+
+  // Store string table entry states.
+  std::map<int, StringEntry> DynamicSectionStrings;
 };
 
 //----------------------------------------------------------------------------
@@ -173,8 +199,8 @@
     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 @@
       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 @@
 
   // 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 @@
                     ByteOrderType order):
   cmELFInternal(external, fin, order)
 {
-  // Initialize state.
-  this->SONameChecked = false;
-
   // Read the main header.
   if(!this->Read(this->ELFHeader))
     {
@@ -424,20 +470,29 @@
 
 //----------------------------------------------------------------------------
 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 @@
   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 @@
 //----------------------------------------------------------------------------
 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;
     }
 }
 



More information about the Cmake-commits mailing list