summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Apolloner <florian@apolloner.eu>2017-03-06 20:16:42 (GMT)
committerBrad King <brad.king@kitware.com>2017-03-10 15:54:53 (GMT)
commita52faa1fcb7b54026ecfbef573d05568846e1aba (patch)
tree0ec71817719dc1f076787fc21bf892df7f334a51
parent0a312e2271710554f8e73518dc4b28bd1d0d1d7a (diff)
downloadCMake-a52faa1fcb7b54026ecfbef573d05568846e1aba.zip
CMake-a52faa1fcb7b54026ecfbef573d05568846e1aba.tar.gz
CMake-a52faa1fcb7b54026ecfbef573d05568846e1aba.tar.bz2
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.
-rw-r--r--Source/cmFileCommand.cxx69
-rw-r--r--Source/cmFileCommand.h1
-rw-r--r--Tests/RunCMake/file/READ_ELF-result.txt1
-rw-r--r--Tests/RunCMake/file/READ_ELF-stderr.txt2
-rw-r--r--Tests/RunCMake/file/READ_ELF.cmake2
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake1
6 files changed, 76 insertions, 0 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 91cecb3..957b4cb 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -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);
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 319864c..2d82a23 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -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);
diff --git a/Tests/RunCMake/file/READ_ELF-result.txt b/Tests/RunCMake/file/READ_ELF-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/READ_ELF-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/READ_ELF-stderr.txt b/Tests/RunCMake/file/READ_ELF-stderr.txt
new file mode 100644
index 0000000..7b32804
--- /dev/null
+++ b/Tests/RunCMake/file/READ_ELF-stderr.txt
@@ -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\.
diff --git a/Tests/RunCMake/file/READ_ELF.cmake b/Tests/RunCMake/file/READ_ELF.cmake
new file mode 100644
index 0000000..cd02c9b
--- /dev/null
+++ b/Tests/RunCMake/file/READ_ELF.cmake
@@ -0,0 +1,2 @@
+file(READ_ELF XXX)
+file(READ_ELF XXX RPATH YYY)
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 7497544..3f3c0da 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -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