diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx index 9ce403dcc05..99707a3f705 100644 --- a/Source/cmBinUtilsLinuxELFLinker.cxx +++ b/Source/cmBinUtilsLinuxELFLinker.cxx @@ -18,6 +18,10 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#ifdef CMake_USE_ELF_PARSER +# include "cmELF.h" +#endif + static std::string ReplaceOrigin(const std::string& rpath, const std::string& origin) { @@ -86,6 +90,24 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( std::string const& file, cmStateEnums::TargetType /* unused */) { std::vector parentRpaths; + +#ifdef CMake_USE_ELF_PARSER + cmELF elf(file.c_str()); + if (!elf) { + return false; + } + if (elf.GetMachine() != 0) { + if (this->Machine != 0) { + if (elf.GetMachine() != this->Machine) { + this->SetError("All files must have the same architecture."); + return false; + } + } else { + this->Machine = elf.GetMachine(); + } + } +#endif + return this->ScanDependencies(file, parentRpaths); } @@ -150,13 +172,29 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( return true; } +namespace { +bool FileHasArchitecture(const char* filename, std::uint16_t machine) +{ +#ifdef CMake_USE_ELF_PARSER + cmELF elf(filename); + if (!elf) { + return false; + } + return machine == 0 || machine == elf.GetMachine(); +#else + return true; +#endif +} +} + bool cmBinUtilsLinuxELFLinker::ResolveDependency( std::string const& name, std::vector const& searchPaths, std::string& path, bool& resolved) { for (auto const& searchPath : searchPaths) { path = cmStrCat(searchPath, '/', name); - if (cmSystemTools::PathExists(path)) { + if (cmSystemTools::PathExists(path) && + FileHasArchitecture(path.c_str(), this->Machine)) { resolved = true; return true; } @@ -164,7 +202,8 @@ bool cmBinUtilsLinuxELFLinker::ResolveDependency( for (auto const& searchPath : this->Archive->GetSearchDirectories()) { path = cmStrCat(searchPath, '/', name); - if (cmSystemTools::PathExists(path)) { + if (cmSystemTools::PathExists(path) && + FileHasArchitecture(path.c_str(), this->Machine)) { std::ostringstream warning; warning << "Dependency " << name << " found in search directory:\n " << searchPath diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h index 4e7e36d4c8b..395ed567b48 100644 --- a/Source/cmBinUtilsLinuxELFLinker.h +++ b/Source/cmBinUtilsLinuxELFLinker.h @@ -3,6 +3,9 @@ #pragma once +#include "cmConfigure.h" // IWYU pragma: keep + +#include #include #include #include @@ -29,6 +32,7 @@ class cmBinUtilsLinuxELFLinker : public cmBinUtilsLinker std::unique_ptr LDConfigTool; bool HaveLDConfigPaths = false; std::vector LDConfigPaths; + std::uint16_t Machine = 0; bool ScanDependencies(std::string const& file, std::vector const& parentRpaths); diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index deffdb6467c..9a474e32c57 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -168,6 +168,9 @@ class cmELFInternal // Return the recorded ELF type. cmELF::FileType GetFileType() const { return this->ELFType; } + // Return the recorded machine. + std::uint16_t GetMachine() const { return this->Machine; } + protected: // Data common to all ELF class implementations. @@ -183,6 +186,9 @@ class cmELFInternal // The ELF file type. cmELF::FileType ELFType; + // The ELF architecture. + std::uint16_t Machine; + // Whether we need to byte-swap structures read from the stream. bool NeedSwap; @@ -478,6 +484,8 @@ cmELFInternalImpl::cmELFInternalImpl(cmELF* external, } } + this->Machine = this->ELFHeader.e_machine; + // Load the section headers. this->SectionHeaders.resize(this->ELFHeader.e_shnum); for (ELF_Half i = 0; i < this->ELFHeader.e_shnum; ++i) { @@ -757,6 +765,14 @@ cmELF::FileType cmELF::GetFileType() const return FileTypeInvalid; } +std::uint16_t cmELF::GetMachine() const +{ + if (this->Valid()) { + return this->Internal->GetMachine(); + } + return 0; +} + unsigned int cmELF::GetNumberOfSections() const { if (this->Valid()) { diff --git a/Source/cmELF.h b/Source/cmELF.h index c479e2b951d..f88ebe99208 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include #include #include #include @@ -72,6 +73,9 @@ class cmELF /** Get the type of the file opened. */ FileType GetFileType() const; + /** Get the machine of the file opened. */ + std::uint16_t GetMachine() const; + /** Get the number of ELF sections present. */ unsigned int GetNumberOfSections() const; diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt index d9758c579e2..5b863220abc 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt @@ -1,5 +1,2 @@ ^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): - file Failed to run objdump on: - - [^ -]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-build/root-all/bin/\.\./lib/libtest\.so$ + file Could not resolve file libtest\.so$