file: Add READ_ELF command to parse ELF binaries

Leave it undocumented for now because we intend to use it internally and
it cannot be made available everywhere.
This commit is contained in:
Florian Apolloner 2017-03-06 21:16:42 +01:00 committed by Brad King
parent 0a312e2271
commit a52faa1fcb
6 changed files with 76 additions and 0 deletions

View File

@ -42,6 +42,10 @@
#include "cmFileLockResult.h"
#endif
#if defined(CMAKE_USE_ELF_PARSER)
#include "cmELF.h"
#endif
class cmSystemToolsFileTime;
// Table of permissions flags.
@ -166,6 +170,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "RPATH_REMOVE") {
return this->HandleRPathRemoveCommand(args);
}
if (subCommand == "READ_ELF") {
return this->HandleReadElfCommand(args);
}
if (subCommand == "RELATIVE_PATH") {
return this->HandleRelativePathCommand(args);
}
@ -2177,6 +2184,68 @@ bool cmFileCommand::HandleRPathCheckCommand(
return true;
}
bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args)
{
if (args.size() < 4) {
this->SetError("READ_ELF must be called with at least three additional "
"arguments.");
return false;
}
cmCommandArgumentsHelper argHelper;
cmCommandArgumentGroup group;
cmCAString readArg(&argHelper, "READ_ELF");
cmCAString fileNameArg(&argHelper, CM_NULLPTR);
cmCAString rpathArg(&argHelper, "RPATH", &group);
cmCAString runpathArg(&argHelper, "RUNPATH", &group);
cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group);
readArg.Follows(CM_NULLPTR);
fileNameArg.Follows(&readArg);
group.Follows(&fileNameArg);
argHelper.Parse(&args, CM_NULLPTR);
if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) {
std::ostringstream e;
e << "READ_ELF given FILE \"" << fileNameArg.GetString()
<< "\" that does not exist.";
this->SetError(e.str());
return false;
}
#if defined(CMAKE_USE_ELF_PARSER)
cmELF elf(fileNameArg.GetCString());
if (!rpathArg.GetString().empty()) {
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
std::string rpath(se_rpath->Value);
std::replace(rpath.begin(), rpath.end(), ':', ';');
this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str());
}
}
if (!runpathArg.GetString().empty()) {
if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
std::string runpath(se_runpath->Value);
std::replace(runpath.begin(), runpath.end(), ':', ';');
this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str());
}
}
return true;
#else
std::string error = "ELF parser not available on this platform.";
if (errorArg.GetString().empty()) {
this->SetError(error);
return false;
} else {
this->Makefile->AddDefinition(errorArg.GetString(), error.c_str());
return true;
}
#endif
}
bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
{
cmFileInstaller installer(this);

View File

@ -53,6 +53,7 @@ protected:
bool HandleRelativePathCommand(std::vector<std::string> const& args);
bool HandleCMakePathCommand(std::vector<std::string> const& args,
bool nativePath);
bool HandleReadElfCommand(std::vector<std::string> const& args);
bool HandleRPathChangeCommand(std::vector<std::string> const& args);
bool HandleRPathCheckCommand(std::vector<std::string> const& args);
bool HandleRPathRemoveCommand(std::vector<std::string> const& args);

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
.*file READ_ELF must be called with at least three additional arguments\.
.*file READ_ELF given FILE "XXX" that does not exist\.

View File

@ -0,0 +1,2 @@
file(READ_ELF XXX)
file(READ_ELF XXX RPATH YYY)

View File

@ -25,6 +25,7 @@ run_cmake(LOCK-error-no-timeout)
run_cmake(LOCK-error-timeout)
run_cmake(LOCK-error-unknown-option)
run_cmake(LOCK-lowercase)
run_cmake(READ_ELF)
run_cmake(GLOB)
run_cmake(GLOB_RECURSE)
# test is valid both for GLOB and GLOB_RECURSE