[Cmake-commits] [cmake-commits] king committed cmSystemTools.cxx 1.380 1.381

cmake-commits at cmake.org cmake-commits at cmake.org
Thu Aug 14 09:53:23 EDT 2008


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

Modified Files:
	cmSystemTools.cxx 
Log Message:
BUG: Update both RPATH and RUNPATH entries

During installation the RPATH and RUNPATH entries of ELF binaries are
edited to match the user specification.  Usually either one entry is
present or both entries refer to the same string literal.  In the case
that they are both present and refer to separate string literals we need
to update both.  I have never seen this case in practice, but we should
do this just in case.


Index: cmSystemTools.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmSystemTools.cxx,v
retrieving revision 1.380
retrieving revision 1.381
diff -C 2 -d -r1.380 -r1.381
*** cmSystemTools.cxx	14 Aug 2008 13:53:17 -0000	1.380
--- cmSystemTools.cxx	14 Aug 2008 13:53:21 -0000	1.381
***************
*** 2330,2333 ****
--- 2330,2343 ----
  #endif
  
+ #if defined(CMAKE_USE_ELF_PARSER)
+ struct cmSystemToolsRPathInfo
+ {
+   unsigned long Position;
+   unsigned long Size;
+   std::string Name;
+   std::string Value;
+ };
+ #endif
+ 
  //----------------------------------------------------------------------------
  bool cmSystemTools::ChangeRPath(std::string const& file,
***************
*** 2342,2376 ****
      *changed = false;
      }
!   unsigned long rpathPosition = 0;
!   unsigned long rpathSize = 0;
!   std::string rpathPrefix;
!   std::string rpathSuffix;
    {
    // 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)
      {
      // Make sure the current rpath contains the old rpath.
!     std::string::size_type pos = cmSystemToolsFindRPath(se->Value, oldRPath);
      if(pos == std::string::npos)
        {
        // If it contains the new rpath instead then it is okay.
!       if(cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
          {
!         return true;
          }
        if(emsg)
          {
          cmOStringStream e;
!         e << "The current RPATH is:\n"
!           << "  " << se->Value << "\n"
            << "which does not contain:\n"
            << "  " << oldRPath << "\n"
--- 2352,2420 ----
      *changed = false;
      }
!   int rp_count = 0;
!   cmSystemToolsRPathInfo rp[2];
    {
    // Parse the ELF binary.
    cmELF elf(file.c_str());
  
!   // Get the RPATH and RUNPATH entries from it.
!   int se_count = 0;
!   cmELF::StringEntry const* se[2] = {0, 0};
!   const char* se_name[2] = {0, 0};
!   if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
      {
!     se[se_count] = se_rpath;
!     se_name[se_count] = "RPATH";
!     ++se_count;
!     }
!   if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
!     {
!     se[se_count] = se_runpath;
!     se_name[se_count] = "RUNPATH";
!     ++se_count;
!     }
!   if(se_count == 0)
!     {
!     if(newRPath.empty())
!       {
!       // The new rpath is empty and there is no rpath anyway so it is
!       // okay.
!       return true;
!       }
!     else
!       {
!       if(emsg)
!         {
!         *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
!         *emsg += elf.GetErrorMessage();
!         }
!       return false;
!       }
      }
  
!   for(int i=0; i < se_count; ++i)
      {
+     // If both RPATH and RUNPATH refer to the same string literal it
+     // needs to be changed only once.
+     if(rp_count && rp[0].Position == se[i]->Position)
+       {
+       continue;
+       }
+ 
      // Make sure the current rpath contains the old rpath.
!     std::string::size_type pos =
!       cmSystemToolsFindRPath(se[i]->Value, oldRPath);
      if(pos == std::string::npos)
        {
        // If it contains the new rpath instead then it is okay.
!       if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
          {
!         continue;
          }
        if(emsg)
          {
          cmOStringStream e;
!         e << "The current " << se_name[i] << " is:\n"
!           << "  " << se[i]->Value << "\n"
            << "which does not contain:\n"
            << "  " << oldRPath << "\n"
***************
*** 2381,2425 ****
        }
  
!     // Store information about the entry.
!     rpathPosition = se->Position;
!     rpathSize = se->Size;
  
!     // Store the part of the path we must preserve.
!     rpathPrefix = se->Value.substr(0, pos);
!     rpathSuffix = se->Value.substr(pos+oldRPath.length(), oldRPath.npos);
!     }
!   else if(newRPath.empty())
!     {
!     // The new rpath is empty and there is no rpath anyway so it is
!     // okay.
!     return true;
!     }
!   else
!     {
!     if(emsg)
        {
!       *emsg = "No valid ELF RPATH entry exists in the file; ";
!       *emsg += elf.GetErrorMessage();
        }
!     return false;
      }
    }
-   // Compute the full new rpath.
-   std::string rpath = rpathPrefix;
-   rpath += newRPath;
-   rpath += rpathSuffix;
  
!   // Make sure there is enough room to store the new rpath and at
!   // least one null terminator.
!   if(rpathSize < rpath.length()+1)
      {
!     if(emsg)
!       {
!       *emsg = "The replacement RPATH is too long.";
!       }
!     return false;
      }
  
!   // Open the file for update and seek to the RPATH position.
    std::ofstream f(file.c_str(),
                    std::ios::in | std::ios::out | std::ios::binary);
--- 2425,2465 ----
        }
  
!     // Store information about the entry in the file.
!     rp[rp_count].Position = se[i]->Position;
!     rp[rp_count].Size = se[i]->Size;
!     rp[rp_count].Name = se_name[i];
  
!     // Construct the new value which preserves the part of the path
!     // not being changed.
!     rp[rp_count].Value = se[i]->Value.substr(0, pos);
!     rp[rp_count].Value += newRPath;
!     rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
!                                               oldRPath.npos);
! 
!     // Make sure there is enough room to store the new rpath and at
!     // least one null terminator.
!     if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
        {
!       if(emsg)
!         {
!         *emsg = "The replacement path is too long for the ";
!         *emsg += se_name[i];
!         *emsg += " entry.";
!         }
!       return false;
        }
! 
!     // This entry is ready for update.
!     ++rp_count;
      }
    }
  
!   // If no runtime path needs to be changed, we are done.
!   if(rp_count == 0)
      {
!     return true;
      }
  
!   // Open the file for update.
    std::ofstream f(file.c_str(),
                    std::ios::in | std::ios::out | std::ios::binary);
***************
*** 2432,2469 ****
      return false;
      }
!   if(!f.seekp(rpathPosition))
      {
!     if(emsg)
        {
!       *emsg = "Error seeking to RPATH position.";
        }
-     return false;
-     }
  
!   // Write the new rpath.  Follow it with enough null terminators to
!   // fill the string table entry.
!   f << rpath;
!   for(unsigned long i=rpath.length(); i < rpathSize; ++i)
!     {
!     f << '\0';
!     }
  
!   // Make sure everything was okay.
!   if(f)
!     {
!     if(changed)
        {
!       *changed = true;
        }
-     return true;
      }
!   else
      {
!     if(emsg)
!       {
!       *emsg = "Error writing the new rpath to the file.";
!       }
!     return false;
      }
  #else
    (void)file;
--- 2472,2518 ----
      return false;
      }
! 
!   // Store the new RPATH and RUNPATH strings.
!   for(int i=0; i < rp_count; ++i)
      {
!     // Seek to the RPATH position.
!     if(!f.seekp(rp[i].Position))
        {
!       if(emsg)
!         {
!         *emsg = "Error seeking to ";
!         *emsg += rp[i].Name;
!         *emsg += " position.";
!         }
!       return false;
        }
  
!     // Write the new rpath.  Follow it with enough null terminators to
!     // fill the string table entry.
!     f << rp[i].Value;
!     for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
!       {
!       f << '\0';
!       }
  
!     // Make sure it wrote correctly.
!     if(!f)
        {
!       if(emsg)
!         {
!         *emsg = "Error writing the new ";
!         *emsg += rp[i].Name;
!         *emsg += " string to the file.";
!         }
!       return false;
        }
      }
! 
!   // Everything was updated successfully.
!   if(changed)
      {
!     *changed = true;
      }
+   return true;
  #else
    (void)file;



More information about the Cmake-commits mailing list