diff options
author | Brad King <brad.king@kitware.com> | 2021-06-25 11:26:27 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2021-06-25 11:26:35 (GMT) |
commit | a6b075c3f8306a6192e66206252d76e2e5925432 (patch) | |
tree | c42e9c053fe5c0f4f536bb97316ae259bc395052 /Source | |
parent | 5840b53a0535955cdc66982de8a18ce39d56b460 (diff) | |
parent | 115ff6a347a96eb77abcd8df5e72e4851dcea414 (diff) | |
download | CMake-a6b075c3f8306a6192e66206252d76e2e5925432.zip CMake-a6b075c3f8306a6192e66206252d76e2e5925432.tar.gz CMake-a6b075c3f8306a6192e66206252d76e2e5925432.tar.bz2 |
Merge topic 'import-elf'
115ff6a347 cmELF: Include the ELF parsing code unconditionally
5dfa3ddbe5 cmELF: Allow building without system ELF headers
0da1540aaa cmELF: Fix check for TagMipsRldMapRel
e21188df8b cmELF: Open file explicitly in binary mode
70cdb36d25 Merge branch 'upstream-elf' into import-elf
7a0a37ca41 elf 2021-06-23 (f13da247)
18038042ed cmelf: Add script to import the FreeBSD ELF headers
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !6240
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeLists.txt | 38 | ||||
-rw-r--r-- | Source/cmConfigure.cmake.h.in | 1 | ||||
-rw-r--r-- | Source/cmELF.cxx | 74 | ||||
-rw-r--r-- | Source/cmELF.h | 7 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 20 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 9 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 39 |
7 files changed, 34 insertions, 154 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9a18184..6446b04 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -10,36 +10,6 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") endif() include(CheckIncludeFile) -# Check if we can build support for ELF parsing. -if(WIN32) - set(HAVE_ELF_H 0) -elseif(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") - CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H) -else() - CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H) -endif() -if(HAVE_ELF_H) - set(CMake_USE_ELF_PARSER 1) -elseif(HAIKU) - # On Haiku, we need to include elf32.h from the private headers - set(CMake_HAIKU_INCLUDE_DIRS - /boot/system/develop/headers/private/system - /boot/system/develop/headers/private/system/arch/x86 - ) - - set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS}) - CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H) - unset(CMAKE_REQUIRED_INCLUDES) - - if(HAVE_ELF32_H) - set(CMake_USE_ELF_PARSER 1) - else() - unset(CMake_HAIKU_INCLUDE_DIRS) - set(CMake_USE_ELF_PARSER) - endif() -else() - set(CMake_USE_ELF_PARSER) -endif() if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) @@ -111,11 +81,6 @@ include_directories( ${CMake_HAIKU_INCLUDE_DIRS} ) -# Check if we can build the ELF parser. -if(CMake_USE_ELF_PARSER) - set(ELF_SRCS cmELF.h cmELF.cxx) -endif() - # Check if we can build the Mach-O parser. if(CMake_USE_MACH_PARSER) set(MACH_SRCS cmMachO.h cmMachO.cxx) @@ -245,7 +210,8 @@ set(SRCS cmDocumentationSection.cxx cmDynamicLoader.cxx cmDynamicLoader.h - ${ELF_SRCS} + cmELF.h + cmELF.cxx cmExprParserHelper.cxx cmExportBuildAndroidMKGenerator.h cmExportBuildAndroidMKGenerator.cxx diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index aeca6b4..6a419f6 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -16,7 +16,6 @@ #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE #cmakedefine HAVE_UNSETENV -#cmakedefine CMake_USE_ELF_PARSER #cmakedefine CMake_USE_MACH_PARSER #cmakedefine CMake_USE_XCOFF_PARSER #define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@ diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index deffdb6..cde7cdf 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -17,41 +17,9 @@ #include "cmsys/FStream.hxx" -// Include the ELF format information system header. -#if defined(__OpenBSD__) -# include <elf_abi.h> -#elif defined(__HAIKU__) -# include <elf32.h> -# include <elf64.h> -using Elf32_Ehdr = struct Elf32_Ehdr; -using Elf32_Shdr = struct Elf32_Shdr; -using Elf32_Sym = struct Elf32_Sym; -using Elf32_Rel = struct Elf32_Rel; -using Elf32_Rela = struct Elf32_Rela; -# define ELFMAG0 0x7F -# define ELFMAG1 'E' -# define ELFMAG2 'L' -# define ELFMAG3 'F' -# define ET_NONE 0 -# define ET_REL 1 -# define ET_EXEC 2 -# define ET_DYN 3 -# define ET_CORE 4 -# define EM_386 3 -# define EM_SPARC 2 -# define EM_PPC 20 -#else -# include <elf.h> -#endif -#if defined(__sun) -# include <sys/link.h> // For dynamic section information -#endif -#ifdef _SCO_DS -# include <link.h> // For DT_SONAME etc. -#endif -#ifndef DT_RUNPATH -# define DT_RUNPATH 29 -#endif +#include "cmelf/elf32.h" +#include "cmelf/elf64.h" +#include "cmelf/elf_common.h" // Low-level byte swapping implementation. template <size_t s> @@ -145,6 +113,7 @@ public: virtual std::vector<char> EncodeDynamicEntries( const cmELF::DynamicEntryList&) = 0; virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0; + virtual bool IsMips() const = 0; virtual void PrintInfo(std::ostream& os) const = 0; // Lookup the SONAME in the DYNAMIC section. @@ -212,7 +181,6 @@ struct cmELFTypes32 }; // Configure the implementation template for 64-bit ELF files. -#ifndef _SCO_DS struct cmELFTypes64 { using ELF_Ehdr = Elf64_Ehdr; @@ -222,7 +190,6 @@ struct cmELFTypes64 using tagtype = ::uint64_t; static const char* GetName() { return "64-bit"; } }; -#endif // Parser implementation template. template <class Types> @@ -256,6 +223,8 @@ public: // Lookup a string from the dynamic section with the given tag. StringEntry const* GetDynamicSectionString(unsigned int tag) override; + bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } + // Print information about the ELF file. void PrintInfo(std::ostream& os) const override { @@ -339,16 +308,12 @@ private: eti == ET_CORE) { return true; } -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { return true; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { return true; } -#endif return false; } @@ -459,18 +424,14 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external, break; default: { unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { this->ELFType = cmELF::FileTypeSpecificOS; break; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { this->ELFType = cmELF::FileTypeSpecificProc; break; } -#endif std::ostringstream e; e << "Unknown ELF file type " << eti; this->SetErrorMessage(e.str().c_str()); @@ -673,17 +634,12 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( const long cmELF::TagRPath = DT_RPATH; const long cmELF::TagRunPath = DT_RUNPATH; - -#ifdef DT_MIPS_RLD_MAP_REL const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL; -#else -const long cmELF::TagMipsRldMapRel = 0; -#endif cmELF::cmELF(const char* fname) { // Try to open the file. - auto fin = cm::make_unique<cmsys::ifstream>(fname); + auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary); // Quit now if the file could not be opened. if (!fin || !*fin) { @@ -728,15 +684,11 @@ cmELF::cmELF(const char* fname) // 32-bit ELF this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>( this, std::move(fin), order); - } -#ifndef _SCO_DS - else if (ident[EI_CLASS] == ELFCLASS64) { + } else if (ident[EI_CLASS] == ELFCLASS64) { // 64-bit ELF this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>( this, std::move(fin), order); - } -#endif - else { + } else { this->ErrorMessage = "ELF file class is not 32-bit or 64-bit."; return; } @@ -830,6 +782,14 @@ cmELF::StringEntry const* cmELF::GetRunPath() return nullptr; } +bool cmELF::IsMIPS() const +{ + if (this->Valid()) { + return this->Internal->IsMips(); + } + return false; +} + void cmELF::PrintInfo(std::ostream& os) const { if (this->Valid()) { diff --git a/Source/cmELF.h b/Source/cmELF.h index c479e2b..5807c16 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -10,10 +10,6 @@ #include <utility> #include <vector> -#if !defined(CMake_USE_ELF_PARSER) -# error "This file may be included only if CMake_USE_ELF_PARSER is enabled." -#endif - class cmELFInternal; /** \class cmELF @@ -98,6 +94,9 @@ public: /** Get the RUNPATH field if any. */ StringEntry const* GetRunPath(); + /** Returns true if the ELF file targets a MIPS CPU. */ + bool IsMIPS() const; + /** Print human-readable information about the ELF file. */ void PrintInfo(std::ostream& os) const; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 0ad59c7..1e3076f 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -31,6 +31,7 @@ #include "cmArgumentParser.h" #include "cmCMakePath.h" #include "cmCryptoHash.h" +#include "cmELF.h" #include "cmExecutionStatus.h" #include "cmFSPermissions.h" #include "cmFileCopier.h" @@ -64,10 +65,6 @@ # include "cmFileLockResult.h" #endif -#if defined(CMake_USE_ELF_PARSER) -# include "cmELF.h" -#endif - #if defined(_WIN32) # include <windows.h> #endif @@ -1242,8 +1239,12 @@ bool HandleReadElfCommand(std::vector<std::string> const& args, return false; } -#if defined(CMake_USE_ELF_PARSER) cmELF elf(fileNameArg.c_str()); + if (!elf) { + status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg, + "\" that is not a valid ELF file.")); + return false; + } if (!arguments.RPath.empty()) { if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { @@ -1261,15 +1262,6 @@ bool HandleReadElfCommand(std::vector<std::string> const& args, } return true; -#else - std::string error = "ELF parser not available on this platform."; - if (arguments.Error.empty()) { - status.SetError(error); - return false; - } - status.GetMakefile().AddDefinition(arguments.Error, error); - return true; -#endif } bool HandleInstallCommand(std::vector<std::string> const& args, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 34797c5..f1c695f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2142,7 +2142,6 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const return true; } -#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER) // Enable if the rpath flag uses a separator and the target uses // binaries we know how to edit. std::string ll = this->GetLinkerLanguage(config); @@ -2155,21 +2154,17 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const // CMAKE_EXECUTABLE_FORMAT. if (cmProp fmt = this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) { -# if defined(CMake_USE_ELF_PARSER) if (*fmt == "ELF") { return true; } -# endif -# if defined(CMake_USE_XCOFF_PARSER) +#if defined(CMake_USE_XCOFF_PARSER) if (*fmt == "XCOFF") { return true; } -# endif +#endif } } } -#endif - static_cast<void>(config); return false; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 488e69c..f082ae8 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -20,6 +20,7 @@ #include <cm3p/uv.h> #include "cmDuration.h" +#include "cmELF.h" #include "cmMessageMetadata.h" #include "cmProcessOutput.h" #include "cmRange.h" @@ -46,12 +47,6 @@ # include "cmCryptoHash.h" #endif -#if defined(CMake_USE_ELF_PARSER) -# include "cmELF.h" -#else -class cmELF; -#endif - #if defined(CMake_USE_MACH_PARSER) # include "cmMachO.h" #endif @@ -2448,14 +2443,12 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message, bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath, std::string& soname) { -// For ELF shared libraries use a real parser to get the correct -// soname. -#if defined(CMake_USE_ELF_PARSER) + // For ELF shared libraries use a real parser to get the correct + // soname. cmELF elf(fullPath.c_str()); if (elf) { return elf.GetSOName(soname); } -#endif // If the file is not a symlink we have no guess for its soname. if (!cmSystemTools::FileIsSymlink(fullPath)) { @@ -2543,14 +2536,6 @@ cm::optional<bool> AdjustRPathELF(std::string const& file, const AdjustCallback& adjustCallback, std::string* emsg, bool* changed) { -#if !defined(CMake_USE_ELF_PARSER) - (void)file; - (void)emptyCallback; - (void)adjustCallback; - (void)emsg; - (void)changed; - return cm::nullopt; // Cannot handle ELF files. -#else if (changed) { *changed = false; } @@ -2678,7 +2663,6 @@ cm::optional<bool> AdjustRPathELF(std::string const& file, *changed = true; } return true; -#endif } std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback( @@ -2690,16 +2674,11 @@ std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback( // okay. return true; } -#if defined(CMake_USE_ELF_PARSER) if (emsg) { *emsg = cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ", elf.GetErrorMessage()); } -#else - static_cast<void>(emsg); - static_cast<void>(elf); -#endif return false; }; } @@ -3033,12 +3012,6 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs) static cm::optional<bool> RemoveRPathELF(std::string const& file, std::string* emsg, bool* removed) { -#if !defined(CMake_USE_ELF_PARSER) - (void)file; - (void)emsg; - (void)removed; - return cm::nullopt; // Cannot handle ELF files. -#else if (removed) { *removed = false; } @@ -3102,8 +3075,7 @@ static cm::optional<bool> RemoveRPathELF(std::string const& file, entriesErased++; continue; } - if (cmELF::TagMipsRldMapRel != 0 && - it->first == cmELF::TagMipsRldMapRel) { + if (it->first == cmELF::TagMipsRldMapRel && elf.IsMIPS()) { // Background: debuggers need to know the "linker map" which contains // the addresses each dynamic object is loaded at. Most arches use // the DT_DEBUG tag which the dynamic linker writes to (directly) and @@ -3178,7 +3150,6 @@ static cm::optional<bool> RemoveRPathELF(std::string const& file, *removed = true; } return true; -#endif } static cm::optional<bool> RemoveRPathXCOFF(std::string const& file, @@ -3225,7 +3196,6 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, 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()); if (elf) { @@ -3248,7 +3218,6 @@ bool cmSystemTools::CheckRPath(std::string const& file, } return false; } -#endif #if defined(CMake_USE_XCOFF_PARSER) // Parse the XCOFF binary. cmXCOFF xcoff(file.c_str()); |