ENH: Added RPATH methods to cmSystemTools
- RemoveRPath to remove the RPATH from a binary - CheckRPath to check for an existing RPATH in a binary
This commit is contained in:
parent
3ff5404cca
commit
b9a5dccc8d
|
@ -2463,3 +2463,173 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#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
|
||||||
|
}
|
||||||
|
|
|
@ -393,6 +393,14 @@ public:
|
||||||
std::string const& newRPath,
|
std::string const& newRPath,
|
||||||
std::string* emsg = 0);
|
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:
|
private:
|
||||||
static bool s_ForceUnixPaths;
|
static bool s_ForceUnixPaths;
|
||||||
static bool s_RunCommandHideConsole;
|
static bool s_RunCommandHideConsole;
|
||||||
|
|
Loading…
Reference in New Issue