summaryrefslogtreecommitdiffstats
path: root/Source/cmSystemTools.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-08-14 13:53:17 (GMT)
committerBrad King <brad.king@kitware.com>2008-08-14 13:53:17 (GMT)
commit2a85f8289fff008d9bfb82f8081cd05008c144c9 (patch)
treec01e389a6915ca8c04c3dc5ed529d136caa78579 /Source/cmSystemTools.cxx
parent777e2d328a610d50a535de6a9e510edd90a4f9cd (diff)
downloadCMake-2a85f8289fff008d9bfb82f8081cd05008c144c9.zip
CMake-2a85f8289fff008d9bfb82f8081cd05008c144c9.tar.gz
CMake-2a85f8289fff008d9bfb82f8081cd05008c144c9.tar.bz2
BUG: Remove both RPATH and RUNPATH entries
Removal of the RPATH and RUNPATH from ELF binaries must work when both entries are present. Both entries should be removed. Previously only one would be removed and the other would be blanked because it pointed at the same string which was zeroed. This fixes gentoo bug number 224901.
Diffstat (limited to 'Source/cmSystemTools.cxx')
-rw-r--r--Source/cmSystemTools.cxx154
1 files changed, 92 insertions, 62 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 4e1f945..f4ce41c 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -26,6 +26,7 @@
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include <cmsys/Terminal.h>
#endif
+#include <cmsys/stl/algorithm>
#if defined(_WIN32)
# include <windows.h>
@@ -2478,54 +2479,87 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
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;
+ int zeroCount = 0;
+ unsigned long zeroPosition[2] = {0,0};
+ unsigned long zeroSize[2] = {0,0};
+ unsigned long bytesBegin = 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)
+ // Get the RPATH and RUNPATH entries from it and sort them by index
+ // in the dynamic section header.
+ 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(se)
+ if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
{
- // Store information about the entry.
- rpathPosition = se->Position;
- rpathSize = se->Size;
- rpathEntryPosition = elf.GetDynamicEntryPosition(se->IndexInSection);
+ se[se_count++] = se_runpath;
+ }
+ if(se_count == 0)
+ {
+ // 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
- // after the RPATH entry.
- unsigned long nextEntryPosition =
- elf.GetDynamicEntryPosition(se->IndexInSection+1);
- unsigned int count = elf.GetDynamicEntryCount();
- if(count == 0)
+ // Get the size of the dynamic section header.
+ 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)
{
- // 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;
+ *emsg = "DYNAMIC section contains a DT_NULL before the end.";
}
- unsigned long nullEntryPosition = elf.GetDynamicEntryPosition(count);
+ return false;
+ }
- // Allocate and fill a buffer with zeros.
- bytes.resize(nullEntryPosition - rpathEntryPosition, 0);
+ // 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);
- // 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]))
+ // 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 a buffer to hold the part of the file to be written.
+ // Initialize it with zeros.
+ bytes.resize(bytesEnd - bytesBegin, 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.
+ char* data = &bytes[0];
+ for(int i=0; i < se_count; ++i)
+ {
+ // 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)
{
@@ -2533,11 +2567,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg)
}
return false;
}
- }
- else
- {
- // There is no RPATH or RUNPATH anyway.
- return true;
+ data += sz;
}
}
@@ -2554,7 +2584,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg)
}
// Write the new DYNAMIC table header.
- if(!f.seekp(rpathEntryPosition))
+ if(!f.seekp(bytesBegin))
{
if(emsg)
{
@@ -2571,33 +2601,33 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg)
return false;
}
- // Fill the RPATH string with zero bytes.
- if(!f.seekp(rpathPosition))
+ // Fill the RPATH and RUNPATH strings with zero bytes.
+ 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;
}
- return false;
- }
- for(unsigned long i=0; i < rpathSize; ++i)
- {
- f << '\0';
- }
-
- // Make sure everything was okay.
- if(f)
- {
- return true;
- }
- else
- {
- if(emsg)
+ for(unsigned long j=0; j < zeroSize[i]; ++j)
{
- *emsg = "Error writing the empty rpath to the file.";
+ f << '\0';
+ }
+ if(!f)
+ {
+ if(emsg)
+ {
+ *emsg = "Error writing the empty rpath string to the file.";
+ }
+ return false;
}
- return false;
}
+
+ // Everything was updated successfully.
+ return true;
#else
(void)file;
(void)emsg;