ENH: Add ELF file parsing
- Enabled when system provides elf.h - Introduce cmELF class to parse ELF files - Use in cmSystemTools::GuessLibrarySOName to really get soname
This commit is contained in:
parent
69ad23a6e7
commit
4c137bad6b
|
@ -1,3 +1,11 @@
|
|||
# Check if we can build support for ELF parsing.
|
||||
CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H)
|
||||
IF(HAVE_ELF_H)
|
||||
SET(CMAKE_USE_ELF_PARSER 1)
|
||||
ELSE(HAVE_ELF_H)
|
||||
SET(CMAKE_USE_ELF_PARSER)
|
||||
ENDIF(HAVE_ELF_H)
|
||||
|
||||
# configure the .h file
|
||||
CONFIGURE_FILE(
|
||||
"${CMake_SOURCE_DIR}/Source/cmConfigure.cmake.h.in"
|
||||
|
@ -75,6 +83,12 @@ IF(CMAKE_REGENERATE_YACCLEX)
|
|||
ENDIF(FLEX_EXECUTABLE)
|
||||
|
||||
ENDIF(CMAKE_REGENERATE_YACCLEX)
|
||||
|
||||
# Check if we can build the ELF parser.
|
||||
IF(CMAKE_USE_ELF_PARSER)
|
||||
SET(ELF_SRCS cmELF.h cmELF.cxx)
|
||||
ENDIF(CMAKE_USE_ELF_PARSER)
|
||||
|
||||
#
|
||||
# Sources for CMakeLib
|
||||
#
|
||||
|
@ -123,6 +137,7 @@ SET(SRCS
|
|||
cmDocumentVariables.cxx
|
||||
cmDynamicLoader.cxx
|
||||
cmDynamicLoader.h
|
||||
${ELF_SRCS}
|
||||
cmExprLexer.cxx
|
||||
cmExprParser.cxx
|
||||
cmExprParserHelper.cxx
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#cmakedefine CMAKE_NO_ANSI_FOR_SCOPE
|
||||
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
|
||||
#cmakedefine HAVE_UNSETENV
|
||||
#cmakedefine CMAKE_USE_ELF_PARSER
|
||||
#cmakedefine CMAKE_STRICT
|
||||
#define CMAKE_ROOT_DIR "${CMake_SOURCE_DIR}"
|
||||
#define CMAKE_BUILD_DIR "${CMake_BINARY_DIR}"
|
||||
|
|
|
@ -0,0 +1,612 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmStandardIncludes.h" // to get CMAKE_USE_ELF_PARSER first
|
||||
#include "cmELF.h"
|
||||
|
||||
#include <cmsys/auto_ptr.hxx>
|
||||
|
||||
// Need the native byte order of the running CPU.
|
||||
#include <cmsys/CPU.h>
|
||||
|
||||
// Include the ELF format information system header.
|
||||
#include <elf.h>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Low-level byte swapping implementation.
|
||||
template <size_t s> struct cmELFByteSwapSize {};
|
||||
void cmELFByteSwap(char*, cmELFByteSwapSize<1> const&)
|
||||
{
|
||||
}
|
||||
void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const&)
|
||||
{
|
||||
char one_byte;
|
||||
one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
|
||||
}
|
||||
void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const&)
|
||||
{
|
||||
char one_byte;
|
||||
one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
|
||||
one_byte = data[1]; data[1] = data[2]; data[2] = one_byte;
|
||||
}
|
||||
void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const&)
|
||||
{
|
||||
char one_byte;
|
||||
one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
|
||||
one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
|
||||
one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
|
||||
one_byte = data[3]; data[3] = data[4]; data[4] = one_byte;
|
||||
}
|
||||
|
||||
// Low-level byte swapping interface.
|
||||
template <typename T>
|
||||
void cmELFByteSwap(T& x)
|
||||
{
|
||||
cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class cmELFInternal
|
||||
{
|
||||
public:
|
||||
enum ByteOrderType { ByteOrderMSB, ByteOrderLSB };
|
||||
|
||||
// Construct and take ownership of the file stream object.
|
||||
cmELFInternal(cmELF* external,
|
||||
cmsys::auto_ptr<std::ifstream>& fin,
|
||||
ByteOrderType order):
|
||||
External(external),
|
||||
Stream(*fin.release()),
|
||||
ByteOrder(order),
|
||||
ELFType(cmELF::FileTypeInvalid)
|
||||
{
|
||||
// Decide whether we need to byte swap fields.
|
||||
#if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE
|
||||
this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
|
||||
#elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG
|
||||
this->NeedSwap = (this->ByteOrder == ByteOrderLSB);
|
||||
#endif
|
||||
|
||||
// We have not yet loaded the section info.
|
||||
this->DynamicSectionIndex = -1;
|
||||
}
|
||||
|
||||
// Destruct and delete the file stream object.
|
||||
~cmELFInternal()
|
||||
{
|
||||
delete &this->Stream;
|
||||
}
|
||||
|
||||
// Forward to the per-class implementation.
|
||||
virtual unsigned int GetNumberOfSections() const = 0;
|
||||
virtual bool GetSOName(std::string& soname) = 0;
|
||||
virtual void PrintInfo(std::ostream& os) const = 0;
|
||||
|
||||
// Return the recorded ELF type.
|
||||
cmELF::FileType GetFileType() const { return this->ELFType; }
|
||||
protected:
|
||||
// Data common to all ELF class implementations.
|
||||
|
||||
// The external cmELF object.
|
||||
cmELF* External;
|
||||
|
||||
// The stream from which to read.
|
||||
std::istream& Stream;
|
||||
|
||||
// The byte order of the ELF file.
|
||||
ByteOrderType ByteOrder;
|
||||
|
||||
// The ELF file type.
|
||||
cmELF::FileType ELFType;
|
||||
|
||||
// Whether we need to byte-swap structures read from the stream.
|
||||
bool NeedSwap;
|
||||
|
||||
// The section header index of the DYNAMIC section (-1 if none).
|
||||
int DynamicSectionIndex;
|
||||
|
||||
// Helper methods for subclasses.
|
||||
void SetErrorMessage(const char* msg)
|
||||
{
|
||||
this->External->ErrorMessage = msg;
|
||||
this->ELFType = cmELF::FileTypeInvalid;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Configure the implementation template for 32-bit ELF files.
|
||||
struct cmELFTypes32
|
||||
{
|
||||
typedef Elf32_Ehdr ELF_Ehdr;
|
||||
typedef Elf32_Shdr ELF_Shdr;
|
||||
typedef Elf32_Dyn ELF_Dyn;
|
||||
typedef Elf32_Half ELF_Half;
|
||||
static const char* GetName() { return "32-bit"; }
|
||||
};
|
||||
|
||||
// Configure the implementation template for 32-bit ELF files.
|
||||
struct cmELFTypes64
|
||||
{
|
||||
typedef Elf64_Ehdr ELF_Ehdr;
|
||||
typedef Elf64_Shdr ELF_Shdr;
|
||||
typedef Elf64_Dyn ELF_Dyn;
|
||||
typedef Elf64_Half ELF_Half;
|
||||
static const char* GetName() { return "64-bit"; }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Parser implementation template.
|
||||
template <class Types>
|
||||
class cmELFInternalImpl: public cmELFInternal
|
||||
{
|
||||
public:
|
||||
// Copy the ELF file format types from our configuration parameter.
|
||||
typedef typename Types::ELF_Ehdr ELF_Ehdr;
|
||||
typedef typename Types::ELF_Shdr ELF_Shdr;
|
||||
typedef typename Types::ELF_Dyn ELF_Dyn;
|
||||
typedef typename Types::ELF_Half ELF_Half;
|
||||
|
||||
// Construct with a stream and byte swap indicator.
|
||||
cmELFInternalImpl(cmELF* external,
|
||||
cmsys::auto_ptr<std::ifstream>& fin,
|
||||
ByteOrderType order);
|
||||
|
||||
// Return the number of sections as specified by the ELF header.
|
||||
virtual unsigned int GetNumberOfSections() const
|
||||
{
|
||||
return static_cast<unsigned int>(this->ELFHeader.e_shnum);
|
||||
}
|
||||
|
||||
// Lookup the SONAME in the DYNAMIC section.
|
||||
virtual bool GetSOName(std::string& soname);
|
||||
|
||||
// Print information about the ELF file.
|
||||
virtual void PrintInfo(std::ostream& os) const
|
||||
{
|
||||
os << "ELF " << Types::GetName();
|
||||
if(this->ByteOrder == ByteOrderMSB)
|
||||
{
|
||||
os << " MSB";
|
||||
}
|
||||
else if(this->ByteOrder == ByteOrderLSB)
|
||||
{
|
||||
os << " LSB";
|
||||
}
|
||||
switch(this->ELFType)
|
||||
{
|
||||
case cmELF::FileTypeRelocatableObject:
|
||||
os << " relocatable object";
|
||||
break;
|
||||
case cmELF::FileTypeExecutable:
|
||||
os << " executable";
|
||||
break;
|
||||
case cmELF::FileTypeSharedLibrary:
|
||||
os << " shared library";
|
||||
break;
|
||||
case cmELF::FileTypeCore:
|
||||
os << " core file";
|
||||
break;
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
private:
|
||||
void ByteSwap(ELF_Ehdr& elf_header)
|
||||
{
|
||||
cmELFByteSwap(elf_header.e_type);
|
||||
cmELFByteSwap(elf_header.e_machine);
|
||||
cmELFByteSwap(elf_header.e_version);
|
||||
cmELFByteSwap(elf_header.e_entry);
|
||||
cmELFByteSwap(elf_header.e_phoff);
|
||||
cmELFByteSwap(elf_header.e_shoff);
|
||||
cmELFByteSwap(elf_header.e_flags);
|
||||
cmELFByteSwap(elf_header.e_ehsize);
|
||||
cmELFByteSwap(elf_header.e_phentsize);
|
||||
cmELFByteSwap(elf_header.e_phnum);
|
||||
cmELFByteSwap(elf_header.e_shentsize);
|
||||
cmELFByteSwap(elf_header.e_shnum);
|
||||
cmELFByteSwap(elf_header.e_shstrndx);
|
||||
}
|
||||
|
||||
void ByteSwap(ELF_Shdr& sec_header)
|
||||
{
|
||||
cmELFByteSwap(sec_header.sh_name);
|
||||
cmELFByteSwap(sec_header.sh_type);
|
||||
cmELFByteSwap(sec_header.sh_flags);
|
||||
cmELFByteSwap(sec_header.sh_addr);
|
||||
cmELFByteSwap(sec_header.sh_offset);
|
||||
cmELFByteSwap(sec_header.sh_size);
|
||||
cmELFByteSwap(sec_header.sh_link);
|
||||
cmELFByteSwap(sec_header.sh_info);
|
||||
cmELFByteSwap(sec_header.sh_addralign);
|
||||
cmELFByteSwap(sec_header.sh_entsize);
|
||||
}
|
||||
|
||||
void ByteSwap(ELF_Dyn& dyn)
|
||||
{
|
||||
cmELFByteSwap(dyn.d_tag);
|
||||
switch (dyn.d_tag)
|
||||
{
|
||||
case DT_NULL: /* dyn.d_un ignored */ break;
|
||||
case DT_NEEDED: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_PLTRELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_PLTGOT: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_HASH: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_STRTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_SYMTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_RELA: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_RELASZ: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_RELAENT: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_STRSZ: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_SYMENT: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_INIT: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_FINI: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_SONAME: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_RPATH: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_SYMBOLIC: /* dyn.d_un ignored */ break;
|
||||
case DT_REL: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_RELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_RELENT: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_PLTREL: cmELFByteSwap(dyn.d_un.d_val); break;
|
||||
case DT_DEBUG: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
case DT_TEXTREL: /* dyn.d_un ignored */ break;
|
||||
case DT_JMPREL: cmELFByteSwap(dyn.d_un.d_ptr); break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Read(ELF_Ehdr& x)
|
||||
{
|
||||
if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
|
||||
this->NeedSwap)
|
||||
{
|
||||
ByteSwap(x);
|
||||
}
|
||||
return this->Stream? true:false;
|
||||
}
|
||||
bool Read(ELF_Shdr& x)
|
||||
{
|
||||
if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
|
||||
this->NeedSwap)
|
||||
{
|
||||
ByteSwap(x);
|
||||
}
|
||||
return this->Stream? true:false;
|
||||
}
|
||||
bool Read(ELF_Dyn& x)
|
||||
{
|
||||
if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
|
||||
this->NeedSwap)
|
||||
{
|
||||
ByteSwap(x);
|
||||
}
|
||||
return this->Stream? true:false;
|
||||
}
|
||||
|
||||
bool LoadSectionHeader(ELF_Half i)
|
||||
{
|
||||
// Read the section header from the file.
|
||||
this->Stream.seekg(this->ELFHeader.e_shoff +
|
||||
this->ELFHeader.e_shentsize * i);
|
||||
if(!this->Read(this->SectionHeaders[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Identify some important sections.
|
||||
if(this->SectionHeaders[i].sh_type == SHT_DYNAMIC)
|
||||
{
|
||||
this->DynamicSectionIndex = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadDynamicSection();
|
||||
|
||||
// Store the main ELF header.
|
||||
ELF_Ehdr ELFHeader;
|
||||
|
||||
// Store all the section headers.
|
||||
std::vector<ELF_Shdr> SectionHeaders;
|
||||
|
||||
// Store all entries of the DYNAMIC section.
|
||||
std::vector<ELF_Dyn> DynamicSectionEntries;
|
||||
|
||||
// Store the SOName if it has been loaded.
|
||||
std::string SOName;
|
||||
bool SONameChecked;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Types>
|
||||
cmELFInternalImpl<Types>
|
||||
::cmELFInternalImpl(cmELF* external,
|
||||
cmsys::auto_ptr<std::ifstream>& fin,
|
||||
ByteOrderType order):
|
||||
cmELFInternal(external, fin, order)
|
||||
{
|
||||
// Initialize state.
|
||||
this->SONameChecked = false;
|
||||
|
||||
// Read the main header.
|
||||
if(!this->Read(this->ELFHeader))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the ELF file type.
|
||||
switch(this->ELFHeader.e_type)
|
||||
{
|
||||
case 1:
|
||||
this->ELFType = cmELF::FileTypeRelocatableObject;
|
||||
break;
|
||||
case 2:
|
||||
this->ELFType = cmELF::FileTypeExecutable;
|
||||
break;
|
||||
case 3:
|
||||
this->ELFType = cmELF::FileTypeSharedLibrary;
|
||||
break;
|
||||
case 4:
|
||||
this->ELFType = cmELF::FileTypeCore;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the section headers.
|
||||
this->SectionHeaders.resize(this->ELFHeader.e_shnum);
|
||||
for(ELF_Half i=0; i < this->ELFHeader.e_shnum; ++i)
|
||||
{
|
||||
if(!this->LoadSectionHeader(i))
|
||||
{
|
||||
this->ELFType = cmELF::FileTypeInvalid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Types>
|
||||
bool cmELFInternalImpl<Types>::LoadDynamicSection()
|
||||
{
|
||||
// If there is no dynamic section we are done.
|
||||
if(this->DynamicSectionIndex < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the section was already loaded we are done.
|
||||
if(!this->DynamicSectionEntries.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allocate the dynamic section entries.
|
||||
ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
|
||||
int n = sec.sh_size / sec.sh_entsize;
|
||||
this->DynamicSectionEntries.resize(n);
|
||||
|
||||
// Read each entry.
|
||||
for(int j=0; j < n; ++j)
|
||||
{
|
||||
// Seek to the beginning of the section entry.
|
||||
this->Stream.seekg(sec.sh_offset + sec.sh_entsize*j);
|
||||
ELF_Dyn& dyn = this->DynamicSectionEntries[j];
|
||||
|
||||
// Try reading the entry.
|
||||
if(!this->Read(dyn))
|
||||
{
|
||||
this->SetErrorMessage("Error reading entry from DYNAMIC section.");
|
||||
this->DynamicSectionIndex = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Types>
|
||||
bool cmELFInternalImpl<Types>::GetSOName(std::string& soname)
|
||||
{
|
||||
// Short-circuit if already checked.
|
||||
if(this->SONameChecked)
|
||||
{
|
||||
soname = this->SOName;
|
||||
return !soname.empty();
|
||||
}
|
||||
this->SONameChecked = true;
|
||||
|
||||
// Try reading the dynamic section.
|
||||
if(!this->LoadDynamicSection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the string table referenced by the DYNAMIC section.
|
||||
ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
|
||||
if(sec.sh_link >= this->SectionHeaders.size())
|
||||
{
|
||||
this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
|
||||
return false;
|
||||
}
|
||||
ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
|
||||
|
||||
// Look for the soname entry.
|
||||
for(typename std::vector<ELF_Dyn>::iterator
|
||||
di = this->DynamicSectionEntries.begin();
|
||||
di != this->DynamicSectionEntries.end(); ++di)
|
||||
{
|
||||
ELF_Dyn& dyn = *di;
|
||||
if(dyn.d_tag == DT_SONAME)
|
||||
{
|
||||
this->Stream.seekg(strtab.sh_offset + dyn.d_un.d_val);
|
||||
char c;
|
||||
while(this->Stream.get(c) && c != 0)
|
||||
{
|
||||
this->SOName += c;
|
||||
}
|
||||
if(!this->Stream)
|
||||
{
|
||||
this->SetErrorMessage("Dynamic section specifies unreadable SONAME.");
|
||||
this->SOName = "";
|
||||
return false;
|
||||
}
|
||||
soname = this->SOName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// External class implementation.
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmELF::cmELF(const char* fname): Internal(0)
|
||||
{
|
||||
// Try to open the file.
|
||||
cmsys::auto_ptr<std::ifstream> fin(new std::ifstream(fname));
|
||||
|
||||
// Quit now if the file could not be opened.
|
||||
if(!fin.get() || !*fin)
|
||||
{
|
||||
this->ErrorMessage = "Error opening input file.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the ELF identification block.
|
||||
char ident[EI_NIDENT];
|
||||
if(!fin->read(ident, EI_NIDENT))
|
||||
{
|
||||
this->ErrorMessage = "Error reading ELF identification.";
|
||||
return;
|
||||
}
|
||||
if(!fin->seekg(0))
|
||||
{
|
||||
this->ErrorMessage = "Error seeking to beginning of file.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the ELF identification.
|
||||
if(!(ident[EI_MAG0] == ELFMAG0 &&
|
||||
ident[EI_MAG1] == ELFMAG1 &&
|
||||
ident[EI_MAG2] == ELFMAG2 &&
|
||||
ident[EI_MAG3] == ELFMAG3))
|
||||
{
|
||||
this->ErrorMessage = "File does not have a valid ELF identification.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the byte order in which the rest of the file is encoded.
|
||||
cmELFInternal::ByteOrderType order;
|
||||
if(ident[EI_DATA] == ELFDATA2LSB)
|
||||
{
|
||||
// File is LSB.
|
||||
order = cmELFInternal::ByteOrderLSB;
|
||||
}
|
||||
else if(ident[EI_DATA] == ELFDATA2MSB)
|
||||
{
|
||||
// File is MSB.
|
||||
order = cmELFInternal::ByteOrderMSB;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ErrorMessage = "ELF file is not LSB or MSB encoded.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the class of the file and construct the corresponding
|
||||
// parser implementation.
|
||||
if(ident[EI_CLASS] == ELFCLASS32)
|
||||
{
|
||||
// 32-bit ELF
|
||||
this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
|
||||
}
|
||||
else if(ident[EI_CLASS] == ELFCLASS64)
|
||||
{
|
||||
// 64-bit ELF
|
||||
this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmELF::~cmELF()
|
||||
{
|
||||
delete this->Internal;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmELF::Valid() const
|
||||
{
|
||||
return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmELF::FileType cmELF::GetFileType() const
|
||||
{
|
||||
if(this->Valid())
|
||||
{
|
||||
return this->Internal->GetFileType();
|
||||
}
|
||||
else
|
||||
{
|
||||
return FileTypeInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
unsigned int cmELF::GetNumberOfSections() const
|
||||
{
|
||||
if(this->Valid())
|
||||
{
|
||||
return this->Internal->GetNumberOfSections();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmELF::GetSOName(std::string& soname)
|
||||
{
|
||||
if(this->Valid() &&
|
||||
this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)
|
||||
{
|
||||
return this->Internal->GetSOName(soname);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmELF::PrintInfo(std::ostream& os) const
|
||||
{
|
||||
if(this->Valid())
|
||||
{
|
||||
this->Internal->PrintInfo(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "Not a valid ELF file.\n";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmELF_h
|
||||
#define cmELF_h
|
||||
|
||||
#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
|
||||
* \brief Executable and Link Format (ELF) parser.
|
||||
*/
|
||||
class cmELF
|
||||
{
|
||||
public:
|
||||
/** Construct with the name of the ELF input file to parse. */
|
||||
cmELF(const char* fname);
|
||||
|
||||
/** Destruct. */
|
||||
~cmELF();
|
||||
|
||||
/** Get the error message if any. */
|
||||
std::string const& GetErrorMessage() const
|
||||
{
|
||||
return this->ErrorMessage;
|
||||
}
|
||||
|
||||
/** Boolean conversion. True if the ELF file is valid. */
|
||||
operator bool() const { return this->Valid(); }
|
||||
|
||||
/** Enumeration of ELF file types. */
|
||||
enum FileType
|
||||
{
|
||||
FileTypeInvalid,
|
||||
FileTypeRelocatableObject,
|
||||
FileTypeExecutable,
|
||||
FileTypeSharedLibrary,
|
||||
FileTypeCore
|
||||
};
|
||||
|
||||
/** Get the type of the file opened. */
|
||||
FileType GetFileType() const;
|
||||
|
||||
/** Get the number of ELF sections present. */
|
||||
unsigned int GetNumberOfSections() const;
|
||||
|
||||
/** Get the SONAME field if any. */
|
||||
bool GetSOName(std::string& soname);
|
||||
|
||||
/** Print human-readable information about the ELF file. */
|
||||
void PrintInfo(std::ostream& os) const;
|
||||
|
||||
private:
|
||||
friend class cmELFInternal;
|
||||
bool Valid() const;
|
||||
cmELFInternal* Internal;
|
||||
std::string ErrorMessage;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -52,6 +52,10 @@
|
|||
# include <cmsys/MD5.h>
|
||||
#endif
|
||||
|
||||
#if defined(CMAKE_USE_ELF_PARSER)
|
||||
# include "cmELF.h"
|
||||
#endif
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
# pragma set woff 1375 /* base class destructor not virtual */
|
||||
#endif
|
||||
|
@ -2155,6 +2159,16 @@ 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)
|
||||
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.c_str()))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue