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;
|
||||
#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* 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;
|
||||
|
|
Loading…
Reference in New Issue