summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZsolt Parragi <zsolt.parragi@cancellar.hu>2019-08-13 12:29:48 (GMT)
committerBrad King <brad.king@kitware.com>2019-08-30 15:30:38 (GMT)
commitc856d4556b4ec28cb818ef3c7aca1e4a30e0499d (patch)
treeaf46514551c74f62952d3d2d5cf2ca34171f9a1c
parent079b8e29168dc081f37f79f3577a5c0690bb7051 (diff)
downloadCMake-c856d4556b4ec28cb818ef3c7aca1e4a30e0499d.zip
CMake-c856d4556b4ec28cb818ef3c7aca1e4a30e0499d.tar.gz
CMake-c856d4556b4ec28cb818ef3c7aca1e4a30e0499d.tar.bz2
bindexplib: supporting llvm bitcode formats using llvm-nm
-rw-r--r--Source/bindexplib.cxx82
-rw-r--r--Source/bindexplib.h5
-rw-r--r--Source/cmMakefileTargetGenerator.cxx7
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx8
-rw-r--r--Source/cmcmd.cxx13
-rw-r--r--Tests/Module/CheckIPOSupported-C/CMakeLists.txt12
-rw-r--r--Tests/Module/CheckIPOSupported-C/bar.c4
-rw-r--r--Tests/Module/CheckIPOSupported-C/main.c3
-rw-r--r--Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt15
-rw-r--r--Tests/Module/CheckIPOSupported-CXX/bar.cpp4
-rw-r--r--Tests/Module/CheckIPOSupported-CXX/main.cpp3
11 files changed, 144 insertions, 12 deletions
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index a107294..7e5db26 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -64,9 +64,12 @@
*/
#include "bindexplib.h"
+#include "cmSystemTools.h"
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
#include <iostream>
+#include <sstream>
+#include <vector>
#include <windows.h>
#ifndef IMAGE_FILE_MACHINE_ARM
@@ -301,7 +304,63 @@ private:
bool IsI386;
};
-bool DumpFile(const char* filename, std::set<std::string>& symbols,
+bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename,
+ std::set<std::string>& symbols,
+ std::set<std::string>& dataSymbols)
+{
+ std::string output;
+ // break up command line into a vector
+ std::vector<std::string> command;
+ command.push_back(nmPath);
+ command.push_back("--no-weak");
+ command.push_back("--defined-only");
+ command.push_back("--format=posix");
+ command.push_back(filename);
+
+ // run the command
+ int exit_code = 0;
+ cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, "",
+ cmSystemTools::OUTPUT_NONE);
+
+ if (exit_code != 0) {
+ fprintf(stderr, "llvm-nm returned an error: %s\n", output.c_str());
+ return false;
+ }
+
+ std::istringstream ss(output);
+ std::string line;
+ while (std::getline(ss, line)) {
+ if (line.empty()) { // last line
+ continue;
+ }
+ size_t sym_end = line.find(" ");
+ if (sym_end == std::string::npos) {
+ fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n",
+ line.c_str());
+ return false;
+ }
+ if (line.size() < sym_end + 1) {
+ fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n",
+ line.c_str());
+ return false;
+ }
+ const std::string sym = line.substr(0, sym_end);
+ const char sym_type = line[sym_end + 1];
+ switch (sym_type) {
+ case 'D':
+ dataSymbols.insert(sym);
+ break;
+ case 'T':
+ symbols.insert(sym);
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool DumpFile(std::string const& nmPath, const char* filename,
+ std::set<std::string>& symbols,
std::set<std::string>& dataSymbols)
{
HANDLE hFile;
@@ -356,16 +415,26 @@ bool DumpFile(const char* filename, std::set<std::string>& symbols,
(imageHeader->Machine == IMAGE_FILE_MACHINE_I386));
symbolDumper.DumpObjFile();
} else {
- // check for /bigobj format
+ // check for /bigobj and llvm LTO format
cmANON_OBJECT_HEADER_BIGOBJ* h =
(cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase;
if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
+ // bigobj
DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols,
dataSymbols, (h->Machine == IMAGE_FILE_MACHINE_I386));
symbolDumper.DumpObjFile();
+ } else if (
+ // BCexCODE - llvm bitcode
+ (h->Sig1 == 0x4342 && h->Sig2 == 0xDEC0) ||
+ // 0x0B17C0DE - llvm bitcode BC wrapper
+ (h->Sig1 == 0x0B17 && h->Sig2 == 0xC0DE)) {
+
+ return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols);
+
} else {
- printf("unrecognized file format in '%s'\n", filename);
+ printf("unrecognized file format in '%s, %u'\n", filename,
+ imageHeader->Machine);
return false;
}
}
@@ -378,7 +447,7 @@ bool DumpFile(const char* filename, std::set<std::string>& symbols,
bool bindexplib::AddObjectFile(const char* filename)
{
- return DumpFile(filename, this->Symbols, this->DataSymbols);
+ return DumpFile(NmPath, filename, this->Symbols, this->DataSymbols);
}
bool bindexplib::AddDefinitionFile(const char* filename)
@@ -419,3 +488,8 @@ void bindexplib::WriteFile(FILE* file)
fprintf(file, "\t%s\n", s.c_str());
}
}
+
+void bindexplib::SetNmPath(std::string const& nm)
+{
+ NmPath = nm;
+}
diff --git a/Source/bindexplib.h b/Source/bindexplib.h
index 3e22ac7..6c066c5 100644
--- a/Source/bindexplib.h
+++ b/Source/bindexplib.h
@@ -12,13 +12,16 @@
class bindexplib
{
public:
- bindexplib() {}
+ bindexplib() { NmPath = "nm"; }
bool AddDefinitionFile(const char* filename);
bool AddObjectFile(const char* filename);
void WriteFile(FILE* file);
+ void SetNmPath(std::string const& nm);
+
private:
std::set<std::string> Symbols;
std::set<std::string> DataSymbols;
+ std::string NmPath;
};
#endif
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index f99fe4e..f84ec76 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -15,6 +15,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLocalCommonGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmMakefileExecutableTargetGenerator.h"
@@ -1738,6 +1739,12 @@ void cmMakefileTargetGenerator::GenDefFile(
this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
cmOutputConverter::SHELL);
+ const char* nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
+ if (nm_executable && *nm_executable) {
+ cmd += " --nm=";
+ cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
+ nm_executable, cmOutputConverter::SHELL);
+ }
real_link_commands.insert(real_link_commands.begin(), cmd);
// create a list of obj files for the -E __create_def to read
cmGeneratedFileStream fout(objlist_file);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 17a5527..df4d45d 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -20,6 +20,7 @@
#include "cmGlobalNinjaGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLinkLineDeviceComputer.h"
+#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
@@ -974,6 +975,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::string obj_list_file = mdi->DefFile + ".objs";
cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
obj_list_file, cmOutputConverter::SHELL);
+
+ const char* nm_executable = GetMakefile()->GetDefinition("CMAKE_NM");
+ if (nm_executable && *nm_executable) {
+ cmd += " --nm=";
+ cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
+ nm_executable, cmOutputConverter::SHELL);
+ }
preLinkCmdLines.push_back(std::move(cmd));
// create a list of obj files for the -E __create_def to read
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 2be8bae..08cad7d 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -558,8 +558,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
else if (args[1] == "__create_def") {
if (args.size() < 4) {
- std::cerr
- << "__create_def Usage: -E __create_def outfile.def objlistfile\n";
+ std::cerr << "__create_def Usage: -E __create_def outfile.def "
+ "objlistfile [-nm=nm-path]\n";
return 1;
}
FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+");
@@ -576,6 +576,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
}
std::string file;
bindexplib deffile;
+ if (args.size() >= 5) {
+ auto a = args[4];
+ if (cmHasLiteralPrefix(a, "--nm=")) {
+ deffile.SetNmPath(a.substr(5));
+ std::cerr << a.substr(5) << "\n";
+ } else {
+ std::cerr << "unknown argument: " << a << "\n";
+ }
+ }
while (cmSystemTools::GetLineFromStream(fin, file)) {
std::string const& ext = cmSystemTools::GetFilenameLastExtension(file);
if (cmSystemTools::LowerCase(ext) == ".def") {
diff --git a/Tests/Module/CheckIPOSupported-C/CMakeLists.txt b/Tests/Module/CheckIPOSupported-C/CMakeLists.txt
index 4a41a98..c5cd03e 100644
--- a/Tests/Module/CheckIPOSupported-C/CMakeLists.txt
+++ b/Tests/Module/CheckIPOSupported-C/CMakeLists.txt
@@ -13,8 +13,18 @@ elseif(CMake_TEST_IPO_WORKS_C)
endif()
add_library(foo foo.c)
+if(NOT CYGWIN AND (NOT WIN32 OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang"))
+ add_library(bar SHARED bar.c)
+ if(WIN32)
+ # Bindexplib for clang supports LTO objects
+ set_target_properties(bar PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
+ endif()
+else()
+ # TODO: bindexplib doesn't support exporting IPO symbols with other compilers on Windows
+ add_library(bar STATIC bar.c)
+endif()
add_executable(CheckIPOSupported-C main.c)
-target_link_libraries(CheckIPOSupported-C PUBLIC foo)
+target_link_libraries(CheckIPOSupported-C PUBLIC foo bar)
enable_testing()
add_test(NAME CheckIPOSupported-C COMMAND CheckIPOSupported-C)
diff --git a/Tests/Module/CheckIPOSupported-C/bar.c b/Tests/Module/CheckIPOSupported-C/bar.c
new file mode 100644
index 0000000..680f213
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-C/bar.c
@@ -0,0 +1,4 @@
+int bar()
+{
+ return 0x42;
+}
diff --git a/Tests/Module/CheckIPOSupported-C/main.c b/Tests/Module/CheckIPOSupported-C/main.c
index 99204ab..28ab26f 100644
--- a/Tests/Module/CheckIPOSupported-C/main.c
+++ b/Tests/Module/CheckIPOSupported-C/main.c
@@ -1,8 +1,9 @@
int foo();
+int bar();
int main()
{
- if (foo() == 0) {
+ if (foo() != bar()) {
return 1;
}
return 0;
diff --git a/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt b/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt
index 1bb2b84..237bf1d 100644
--- a/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt
+++ b/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt
@@ -12,9 +12,20 @@ elseif(CMake_TEST_IPO_WORKS_CXX)
message(FATAL_ERROR "IPO expected to work, but the check failed:\n ${ipo_output}")
endif()
-add_library(foo foo.cpp)
+
+add_library(foo STATIC foo.cpp)
+if(NOT CYGWIN AND (NOT WIN32 OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"))
+ add_library(bar SHARED bar.cpp)
+ if(WIN32)
+ # Bindexplib for clang supports LTO objects
+ set_target_properties(bar PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
+ endif()
+else()
+ # TODO: bindexplib doesn't support exporting IPO symbols with other compilers on Windows
+ add_library(bar STATIC bar.cpp)
+endif()
add_executable(CheckIPOSupported-CXX main.cpp)
-target_link_libraries(CheckIPOSupported-CXX PUBLIC foo)
+target_link_libraries(CheckIPOSupported-CXX PUBLIC foo bar)
enable_testing()
add_test(NAME CheckIPOSupported-CXX COMMAND CheckIPOSupported-CXX)
diff --git a/Tests/Module/CheckIPOSupported-CXX/bar.cpp b/Tests/Module/CheckIPOSupported-CXX/bar.cpp
new file mode 100644
index 0000000..680f213
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CXX/bar.cpp
@@ -0,0 +1,4 @@
+int bar()
+{
+ return 0x42;
+}
diff --git a/Tests/Module/CheckIPOSupported-CXX/main.cpp b/Tests/Module/CheckIPOSupported-CXX/main.cpp
index 99204ab..28ab26f 100644
--- a/Tests/Module/CheckIPOSupported-CXX/main.cpp
+++ b/Tests/Module/CheckIPOSupported-CXX/main.cpp
@@ -1,8 +1,9 @@
int foo();
+int bar();
int main()
{
- if (foo() == 0) {
+ if (foo() != bar()) {
return 1;
}
return 0;