View | Details | Raw Unified
Collapse All | Expand All

(-) cmake-2.6.1-orig/Source/cmFileCommand.cxx (-3 / +14 lines)
 Lines 1486-1492   cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args) Link Here 
  cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew();
  cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew();
  bool have_ft = cmSystemTools::FileTimeGet(file, ft);
  bool have_ft = cmSystemTools::FileTimeGet(file, ft);
  std::string emsg;
  std::string emsg;
  if(!cmSystemTools::RemoveRPath(file, &emsg))
  bool removed;
  if(!cmSystemTools::RemoveRPath(file, &emsg, &removed))
    {
    {
    cmOStringStream e;
    cmOStringStream e;
    e << "RPATH_REMOVE could not remove RPATH from file:\n"
    e << "RPATH_REMOVE could not remove RPATH from file:\n"
 Lines 1495-1503   cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args) Link Here 
    this->SetError(e.str().c_str());
    this->SetError(e.str().c_str());
    success = false;
    success = false;
    }
    }
  if(success && have_ft)
  if(success)
    {
    {
    cmSystemTools::FileTimeSet(file, ft);
    if(removed)
      {
      std::string message = "Removed runtime path from \"";
      message += file;
      message += "\"";
      this->Makefile->DisplayStatus(message.c_str(), -1);
      }
    if(have_ft)
      {
      cmSystemTools::FileTimeSet(file, ft);
      }
    }
    }
  cmSystemTools::FileTimeDelete(ft);
  cmSystemTools::FileTimeDelete(ft);
  return success;
  return success;
(-) cmake-2.6.1-orig/Source/cmSystemTools.cxx (-132 / +221 lines)
 Lines 26-31    Link Here 
#if defined(CMAKE_BUILD_WITH_CMAKE)
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include <cmsys/Terminal.h>
# include <cmsys/Terminal.h>
#endif
#endif
#include <cmsys/stl/algorithm>
#if defined(_WIN32)
#if defined(_WIN32)
# include <windows.h>
# include <windows.h>
 Lines 2328-2333   std::string::size_type cmSystemToolsFindRPath(std::string const& have, Link Here 
}
}
#endif
#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,
bool cmSystemTools::ChangeRPath(std::string const& file,
                                std::string const& oldRPath,
                                std::string const& oldRPath,
 Lines 2340-2376   bool cmSystemTools::ChangeRPath(std::string const& file, Link Here 
    {
    {
    *changed = false;
    *changed = false;
    }
    }
  unsigned long rpathPosition = 0;
  int rp_count = 0;
  unsigned long rpathSize = 0;
  cmSystemToolsRPathInfo rp[2];
  std::string rpathPrefix;
  std::string rpathSuffix;
  {
  {
  // Parse the ELF binary.
  // Parse the ELF binary.
  cmELF elf(file.c_str());
  cmELF elf(file.c_str());
  // Get the RPATH or RUNPATH entry from it.
  // Get the RPATH and RUNPATH entries from it.
  cmELF::StringEntry const* se = elf.GetRPath();
  int se_count = 0;
  if(!se)
  cmELF::StringEntry const* se[2] = {0, 0};
  const char* se_name[2] = {0, 0};
  if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
    {
    {
    se = elf.GetRunPath();
    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;
      }
    }
    }
  if(se)
  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.
    // Make sure the current rpath contains the old rpath.
    std::string::size_type pos = cmSystemToolsFindRPath(se->Value, oldRPath);
    std::string::size_type pos =
      cmSystemToolsFindRPath(se[i]->Value, oldRPath);
    if(pos == std::string::npos)
    if(pos == std::string::npos)
      {
      {
      // If it contains the new rpath instead then it is okay.
      // If it contains the new rpath instead then it is okay.
      if(cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
      if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
        {
        {
        return true;
        continue;
        }
        }
      if(emsg)
      if(emsg)
        {
        {
        cmOStringStream e;
        cmOStringStream e;
        e << "The current RPATH is:\n"
        e << "The current " << se_name[i] << " is:\n"
          << "  " << se->Value << "\n"
          << "  " << se[i]->Value << "\n"
          << "which does not contain:\n"
          << "which does not contain:\n"
          << "  " << oldRPath << "\n"
          << "  " << oldRPath << "\n"
          << "as was expected.";
          << "as was expected.";
 Lines 2379-2425   bool cmSystemTools::ChangeRPath(std::string const& file, Link Here 
      return false;
      return false;
      }
      }
    // Store information about the entry.
    // Store information about the entry in the file.
    rpathPosition = se->Position;
    rp[rp_count].Position = se[i]->Position;
    rpathSize = se->Size;
    rp[rp_count].Size = se[i]->Size;
    rp[rp_count].Name = se_name[i];
    // Store the part of the path we must preserve.
    // Construct the new value which preserves the part of the path
    rpathPrefix = se->Value.substr(0, pos);
    // not being changed.
    rpathSuffix = se->Value.substr(pos+oldRPath.length(), oldRPath.npos);
    rp[rp_count].Value = se[i]->Value.substr(0, pos);
    }
    rp[rp_count].Value += newRPath;
  else if(newRPath.empty())
    rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
    {
                                              oldRPath.npos);
    // The new rpath is empty and there is no rpath anyway so it is
    // okay.
    // Make sure there is enough room to store the new rpath and at
    return true;
    // least one null terminator.
    }
    if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
  else
    {
    if(emsg)
      {
      {
      *emsg = "No valid ELF RPATH entry exists in the file; ";
      if(emsg)
      *emsg += elf.GetErrorMessage();
        {
        *emsg = "The replacement path is too long for the ";
        *emsg += se_name[i];
        *emsg += " entry.";
        }
      return false;
      }
      }
    return false;
    // This entry is ready for update.
    ++rp_count;
    }
    }
  }
  }
  // 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
  // If no runtime path needs to be changed, we are done.
  // least one null terminator.
  if(rp_count == 0)
  if(rpathSize < rpath.length()+1)
    {
    {
    if(emsg)
    return true;
      {
      *emsg = "The replacement RPATH is too long.";
      }
    return false;
    }
    }
  // Open the file for update and seek to the RPATH position.
  // Open the file for update.
  std::ofstream f(file.c_str(),
  std::ofstream f(file.c_str(),
                  std::ios::in | std::ios::out | std::ios::binary);
                  std::ios::in | std::ios::out | std::ios::binary);
  if(!f)
  if(!f)
 Lines 2430-2469   bool cmSystemTools::ChangeRPath(std::string const& file, Link Here 
      }
      }
    return false;
    return false;
    }
    }
  if(!f.seekp(rpathPosition))
  // Store the new RPATH and RUNPATH strings.
  for(int i=0; i < rp_count; ++i)
    {
    {
    if(emsg)
    // Seek to the RPATH position.
    if(!f.seekp(rp[i].Position))
      {
      {
      *emsg = "Error seeking to RPATH position.";
      if(emsg)
        {
        *emsg = "Error seeking to ";
        *emsg += rp[i].Name;
        *emsg += " position.";
        }
      return false;
      }
      }
    return false;
    }
  // Write the new rpath.  Follow it with enough null terminators to
    // Write the new rpath.  Follow it with enough null terminators to
  // fill the string table entry.
    // fill the string table entry.
  f << rpath;
    f << rp[i].Value;
  for(unsigned long i=rpath.length(); i < rpathSize; ++i)
    for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
    {
      {
    f << '\0';
      f << '\0';
    }
      }
  // Make sure everything was okay.
    // Make sure it wrote correctly.
  if(f)
    if(!f)
    {
    if(changed)
      {
      {
      *changed = true;
      if(emsg)
        {
        *emsg = "Error writing the new ";
        *emsg += rp[i].Name;
        *emsg += " string to the file.";
        }
      return false;
      }
      }
    return true;
    }
    }
  else
  // Everything was updated successfully.
  if(changed)
    {
    {
    if(emsg)
    *changed = true;
      {
      *emsg = "Error writing the new rpath to the file.";
      }
    return false;
    }
    }
  return true;
#else
#else
  (void)file;
  (void)file;
  (void)oldRPath;
  (void)oldRPath;
 Lines 2475-2531   bool cmSystemTools::ChangeRPath(std::string const& file, Link Here 
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg)
bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
                                bool* removed)
{
{
#if defined(CMAKE_USE_ELF_PARSER)
#if defined(CMAKE_USE_ELF_PARSER)
  unsigned long rpathPosition = 0;
  if(removed)
  unsigned long rpathSize = 0;
    {
  unsigned long rpathEntryPosition = 0;
    *removed = false;
    }
  int zeroCount = 0;
  unsigned long zeroPosition[2] = {0,0};
  unsigned long zeroSize[2] = {0,0};
  unsigned long bytesBegin = 0;
  std::vector<char> bytes;
  std::vector<char> bytes;
  {
  {
  // Parse the ELF binary.
  // Parse the ELF binary.
  cmELF elf(file.c_str());
  cmELF elf(file.c_str());
  // Get the RPATH or RUNPATH entry from it.
  // Get the RPATH and RUNPATH entries from it and sort them by index
  cmELF::StringEntry const* se = elf.GetRPath();
  // in the dynamic section header.
  if(!se)
  int se_count = 0;
  cmELF::StringEntry const* se[2] = {0, 0};
  if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
    {
    {
    se = elf.GetRunPath();
    se[se_count++] = se_rpath;
    }
    }
  if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
  if(se)
    {
    {
    // Store information about the entry.
    se[se_count++] = se_runpath;
    rpathPosition = se->Position;
    }
    rpathSize = se->Size;
  if(se_count == 0)
    rpathEntryPosition = elf.GetDynamicEntryPosition(se->IndexInSection);
    {
    // There is no RPATH or RUNPATH anyway.
    return true;
    }
  if(se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection)
    {
    cmsys_stl::swap(se[0], se[1]);
    }
    // Get the file range containing the rest of the DYNAMIC table
  // Get the size of the dynamic section header.
    // after the RPATH entry.
  unsigned int count = elf.GetDynamicEntryCount();
    unsigned long nextEntryPosition =
  if(count == 0)
      elf.GetDynamicEntryPosition(se->IndexInSection+1);
    {
    unsigned int count = elf.GetDynamicEntryCount();
    // This should happen only for invalid ELF files where a DT_NULL
    if(count == 0)
    // appears before the end of the table.
    if(emsg)
      {
      {
      // This should happen only for invalid ELF files where a DT_NULL
      *emsg = "DYNAMIC section contains a DT_NULL before the end.";
      // 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);
    return false;
    }
  // Save information about the string entries to be zeroed.
  zeroCount = se_count;
  for(int i=0; i < se_count; ++i)
    {
    zeroPosition[i] = se[i]->Position;
    zeroSize[i] = se[i]->Size;
    }
  // Get the range of file positions corresponding to each entry and
  // the rest of the table after them.
  unsigned long entryBegin[3] = {0,0,0};
  unsigned long entryEnd[2] = {0,0};
  for(int i=0; i < se_count; ++i)
    {
    entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection);
    entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection+1);
    }
  entryBegin[se_count] = elf.GetDynamicEntryPosition(count);
  // The data are to be written over the old table entries starting at
  // the first one being removed.
  bytesBegin = entryBegin[0];
  unsigned long bytesEnd = entryBegin[se_count];
    // Allocate and fill a buffer with zeros.
  // Allocate a buffer to hold the part of the file to be written.
    bytes.resize(nullEntryPosition - rpathEntryPosition, 0);
  // Initialize it with zeros.
  bytes.resize(bytesEnd - bytesBegin, 0);
    // Read the part of the DYNAMIC section header that will move.
  // Read the part of the DYNAMIC section header that will move.
    // The remainder of the buffer will be left with zeros which
  // The remainder of the buffer will be left with zeros which
    // represent a DT_NULL entry.
  // represent a DT_NULL entry.
    if(!elf.ReadBytes(nextEntryPosition,
  char* data = &bytes[0];
                      nullEntryPosition - nextEntryPosition,
  for(int i=0; i < se_count; ++i)
                      &bytes[0]))
    {
    // Read data between the entries being removed.
    unsigned long sz = entryBegin[i+1] - entryEnd[i];
    if(sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data))
      {
      {
      if(emsg)
      if(emsg)
        {
        {
 Lines 2533-2543   bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg) Link Here 
        }
        }
      return false;
      return false;
      }
      }
    }
    data += sz;
  else
    {
    // There is no RPATH or RUNPATH anyway.
    return true;
    }
    }
  }
  }
 Lines 2554-2560   bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg) Link Here 
    }
    }
  // Write the new DYNAMIC table header.
  // Write the new DYNAMIC table header.
  if(!f.seekp(rpathEntryPosition))
  if(!f.seekp(bytesBegin))
    {
    {
    if(emsg)
    if(emsg)
      {
      {
 Lines 2571-2606   bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg) Link Here 
    return false;
    return false;
    }
    }
  // Fill the RPATH string with zero bytes.
  // Fill the RPATH and RUNPATH strings with zero bytes.
  if(!f.seekp(rpathPosition))
  for(int i=0; i < zeroCount; ++i)
    {
    {
    if(emsg)
    if(!f.seekp(zeroPosition[i]))
      {
      {
      *emsg = "Error seeking to RPATH position.";
      if(emsg)
        {
        *emsg = "Error seeking to RPATH position.";
        }
      return false;
      }
    for(unsigned long j=0; j < zeroSize[i]; ++j)
      {
      f << '\0';
      }
    if(!f)
      {
      if(emsg)
        {
        *emsg = "Error writing the empty rpath string to the file.";
        }
      return false;
      }
      }
    return false;
    }
  for(unsigned long i=0; i < rpathSize; ++i)
    {
    f << '\0';
    }
    }
  // Make sure everything was okay.
  // Everything was updated successfully.
  if(f)
  if(removed)
    {
    return true;
    }
  else
    {
    {
    if(emsg)
    *removed = true;
      {
      *emsg = "Error writing the empty rpath to the file.";
      }
    return false;
    }
    }
  return true;
#else
#else
  (void)file;
  (void)file;
  (void)emsg;
  (void)emsg;
  (void)removed;
  return false;
  return false;
#endif
#endif
}
}
(-) cmake-2.6.1-orig/Source/cmSystemTools.h (-1 / +2 lines)
 Lines 396-402   public: Link Here 
                          bool* changed = 0);
                          bool* changed = 0);
  /** Try to remove the RPATH from an ELF binary.  */
  /** Try to remove the RPATH from an ELF binary.  */
  static bool RemoveRPath(std::string const& file, std::string* emsg = 0);
  static bool RemoveRPath(std::string const& file, std::string* emsg = 0,
                          bool* removed = 0);
  /** Check whether the RPATH in an ELF binary contains the path
  /** Check whether the RPATH in an ELF binary contains the path
      given.  */
      given.  */