summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-04-14 19:02:34 (GMT)
committerBrad King <brad.king@kitware.com>2008-04-14 19:02:34 (GMT)
commitb9a5dccc8da342d72c9bd5563c38cfad55a9ad89 (patch)
tree794ac2bfac46fa2b175472db10244401e931f561
parent3ff5404ccaeefbf4d53efcf86cd3a7d45d8e87e9 (diff)
downloadCMake-b9a5dccc8da342d72c9bd5563c38cfad55a9ad89.zip
CMake-b9a5dccc8da342d72c9bd5563c38cfad55a9ad89.tar.gz
CMake-b9a5dccc8da342d72c9bd5563c38cfad55a9ad89.tar.bz2
ENH: Added RPATH methods to cmSystemTools
- RemoveRPath to remove the RPATH from a binary - CheckRPath to check for an existing RPATH in a binary
-rw-r--r--Source/cmSystemTools.cxx170
-rw-r--r--Source/cmSystemTools.h8
2 files changed, 178 insertions, 0 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 4773755..4d25944 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -2463,3 +2463,173 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
return false;
#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
+}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 18c4939..89cf407 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -393,6 +393,14 @@ public:
std::string const& newRPath,
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;
static bool s_RunCommandHideConsole;