summaryrefslogtreecommitdiffstats
path: root/Source/cmSystemTools.cxx
diff options
context:
space:
mode:
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;