mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-03 12:49:50 -05:00
Merge topic 'import-elf'
115ff6a347cmELF: Include the ELF parsing code unconditionally5dfa3ddbe5cmELF: Allow building without system ELF headers0da1540aaacmELF: Fix check for TagMipsRldMapRele21188df8bcmELF: Open file explicitly in binary mode70cdb36d25Merge branch 'upstream-elf' into import-elf7a0a37ca41elf 2021-06-23 (f13da247)18038042edcmelf: Add script to import the FreeBSD ELF headers Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !6240
This commit is contained in:
+2
-36
@@ -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
|
||||
|
||||
@@ -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@
|
||||
|
||||
+17
-57
@@ -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()) {
|
||||
|
||||
+3
-4
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user