[Cmake-commits] [cmake-commits] king committed cmSystemTools.cxx 1.376 1.377 cmSystemTools.h 1.151 1.152

cmake-commits at cmake.org cmake-commits at cmake.org
Mon Apr 14 15:02:37 EDT 2008


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

Modified Files:
	cmSystemTools.cxx cmSystemTools.h 
Log Message:
ENH: Added RPATH methods to cmSystemTools

  - RemoveRPath to remove the RPATH from a binary
  - CheckRPath to check for an existing RPATH in a binary


Index: cmSystemTools.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmSystemTools.h,v
retrieving revision 1.151
retrieving revision 1.152
diff -C 2 -d -r1.151 -r1.152
*** cmSystemTools.h	14 Apr 2008 15:43:45 -0000	1.151
--- cmSystemTools.h	14 Apr 2008 19:02:34 -0000	1.152
***************
*** 394,397 ****
--- 394,405 ----
                            std::string* emsg = 0);
  
+   /** Try to remove the RPATH from an ELF binary.  */
+   static bool RemoveRPath(std::string const& file, std::string* emsg = 0);
+ 
+   /** Check whether the RPATH in an ELF binary contains the path
+       given.  */
+   static bool CheckRPath(std::string const& file,
+                          std::string const& newRPath);
+ 
  private:
    static bool s_ForceUnixPaths;

Index: cmSystemTools.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmSystemTools.cxx,v
retrieving revision 1.376
retrieving revision 1.377
diff -C 2 -d -r1.376 -r1.377
*** cmSystemTools.cxx	14 Apr 2008 16:44:01 -0000	1.376
--- cmSystemTools.cxx	14 Apr 2008 19:02:33 -0000	1.377
***************
*** 2464,2465 ****
--- 2464,2635 ----
  #endif
  }
+ 
+ //----------------------------------------------------------------------------
+ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg)
+ {
+ #if defined(CMAKE_USE_ELF_PARSER)
+   unsigned long rpathPosition = 0;
+   unsigned long rpathSize = 0;
+   unsigned long rpathEntryPosition = 0;
+   std::vector<char> bytes;
+   {
+   // Parse the ELF binary.
+   cmELF elf(file.c_str());
+ 
+   // Get the RPATH or RUNPATH entry from it.
+   cmELF::StringEntry const* se = elf.GetRPath();
+   if(!se)
+     {
+     se = elf.GetRunPath();
+     }
+ 
+   if(se)
+     {
+     // Store information about the entry.
+     rpathPosition = se->Position;
+     rpathSize = se->Size;
+     rpathEntryPosition = elf.GetDynamicEntryPosition(se->IndexInSection);
+ 
+     // Get the file range containing the rest of the DYNAMIC table
+     // after the RPATH entry.
+     unsigned long nextEntryPosition =
+       elf.GetDynamicEntryPosition(se->IndexInSection+1);
+     unsigned int count = elf.GetDynamicEntryCount();
+     if(count == 0)
+       {
+       // This should happen only for invalid ELF files where a DT_NULL
+       // appears before the end of the table.
+       if(emsg)
+         {
+         *emsg = "DYNAMIC section contains a DT_NULL before the end.";
+         }
+       return false;
+       }
+     unsigned long nullEntryPosition = elf.GetDynamicEntryPosition(count);
+ 
+     // Allocate and fill a buffer with zeros.
+     bytes.resize(nullEntryPosition - rpathEntryPosition, 0);
+ 
+     // Read the part of the DYNAMIC section header that will move.
+     // The remainder of the buffer will be left with zeros which
+     // represent a DT_NULL entry.
+     if(!elf.ReadBytes(nextEntryPosition,
+                       nullEntryPosition - nextEntryPosition,
+                       &bytes[0]))
+       {
+       if(emsg)
+         {
+         *emsg = "Failed to read DYNAMIC section header.";
+         }
+       return false;
+       }
+     }
+   else
+     {
+     // There is no RPATH or RUNPATH anyway.
+     return true;
+     }
+   }
+ 
+   // Open the file for update.
+   std::ofstream f(file.c_str(),
+                   std::ios::in | std::ios::out | std::ios::binary);
+   if(!f)
+     {
+     if(emsg)
+       {
+       *emsg = "Error opening file for update.";
+       }
+     return false;
+     }
+ 
+   // Write the new DYNAMIC table header.
+   if(!f.seekp(rpathEntryPosition))
+     {
+     if(emsg)
+       {
+       *emsg = "Error seeking to DYNAMIC table header for RPATH.";
+       }
+     return false;
+     }
+   if(!f.write(&bytes[0], bytes.size()))
+     {
+     if(emsg)
+       {
+       *emsg = "Error replacing DYNAMIC table header.";
+       }
+     return false;
+     }
+ 
+   // Fill the RPATH string with zero bytes.
+   if(!f.seekp(rpathPosition))
+     {
+     if(emsg)
+       {
+       *emsg = "Error seeking to RPATH position.";
+       }
+     return false;
+     }
+   for(unsigned long i=0; i < rpathSize; ++i)
+     {
+     f << '\0';
+     }
+ 
+   // Make sure everything was okay.
+   if(f)
+     {
+     return true;
+     }
+   else
+     {
+     if(emsg)
+       {
+       *emsg = "Error writing the empty rpath to the file.";
+       }
+     return false;
+     }
+ #else
+   (void)file;
+   (void)emsg;
+   return false;
+ #endif
+ }
+ 
+ //----------------------------------------------------------------------------
+ bool cmSystemTools::CheckRPath(std::string const& file,
+                                std::string const& newRPath)
+ {
+ #if defined(CMAKE_USE_ELF_PARSER)
+   // Parse the ELF binary.
+   cmELF elf(file.c_str());
+ 
+   // Get the RPATH or RUNPATH entry from it.
+   cmELF::StringEntry const* se = elf.GetRPath();
+   if(!se)
+     {
+     se = elf.GetRunPath();
+     }
+ 
+   // Make sure the current rpath contains the new rpath.
+   if(newRPath.empty())
+     {
+     if(!se)
+       {
+       return true;
+       }
+     }
+   else
+     {
+     if(se &&
+        cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
+       {
+       return true;
+       }
+     }
+   return false;
+ #else
+   (void)file;
+   (void)newRPath;
+   return false;
+ #endif
+ }



More information about the Cmake-commits mailing list