206 lines
6.5 KiB
C++
206 lines
6.5 KiB
C++
//===- ELFReader.h --------------------------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#ifndef MCLD_LD_ELFREADER_H_
|
|
#define MCLD_LD_ELFREADER_H_
|
|
|
|
#include "mcld/LD/ELFReaderIf.h"
|
|
#include "mcld/LD/LDSymbol.h"
|
|
#include "mcld/LD/ResolveInfo.h"
|
|
#include "mcld/Target/GNULDBackend.h"
|
|
|
|
#include <llvm/ADT/StringRef.h>
|
|
#include <llvm/Support/ELF.h>
|
|
#include <llvm/Support/Host.h>
|
|
|
|
namespace mcld {
|
|
|
|
class IRBuilder;
|
|
class LDSection;
|
|
class SectionData;
|
|
|
|
/** \class ELFReader
|
|
* \brief ELFReader is a template scaffolding for partial specification.
|
|
*/
|
|
template <size_t BIT, bool LITTLEENDIAN>
|
|
class ELFReader {};
|
|
|
|
/** \class ELFReader<32, true>
|
|
* \brief ELFReader<32, true> is a 32-bit, little endian ELFReader.
|
|
*/
|
|
template <>
|
|
class ELFReader<32, true> : public ELFReaderIF {
|
|
public:
|
|
typedef llvm::ELF::Elf32_Ehdr ELFHeader;
|
|
typedef llvm::ELF::Elf32_Shdr SectionHeader;
|
|
typedef llvm::ELF::Elf32_Sym Symbol;
|
|
typedef llvm::ELF::Elf32_Rel Rel;
|
|
typedef llvm::ELF::Elf32_Rela Rela;
|
|
|
|
public:
|
|
explicit ELFReader(GNULDBackend& pBackend);
|
|
|
|
~ELFReader();
|
|
|
|
/// ELFHeaderSize - return the size of the ELFHeader
|
|
size_t getELFHeaderSize() const { return sizeof(ELFHeader); }
|
|
|
|
/// isELF - is this a ELF file
|
|
bool isELF(const void* pELFHeader) const;
|
|
|
|
/// isMyEndian - is this ELF file in the same endian to me?
|
|
bool isMyEndian(const void* pELFHeader) const;
|
|
|
|
/// isMyMachine - is this ELF file generated for the same machine.
|
|
bool isMyMachine(const void* pELFHeader) const;
|
|
|
|
/// fileType - the file type of this file
|
|
Input::Type fileType(const void* pELFHeader) const;
|
|
|
|
/// readSectionHeaders - read ELF section header table and create LDSections
|
|
bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
|
|
|
|
/// readRegularSection - read a regular section and create fragments.
|
|
bool readRegularSection(Input& pInput, SectionData& pSD) const;
|
|
|
|
/// readSymbols - read ELF symbols and create LDSymbol
|
|
bool readSymbols(Input& pInput,
|
|
IRBuilder& pBuilder,
|
|
llvm::StringRef pRegion,
|
|
const char* StrTab) const;
|
|
|
|
/// readSignature - read a symbol from the given Input and index in symtab
|
|
/// This is used to get the signature of a group section.
|
|
ResolveInfo* readSignature(Input& pInput,
|
|
LDSection& pSymTab,
|
|
uint32_t pSymIdx) const;
|
|
|
|
/// readRela - read ELF rela and create Relocation
|
|
bool readRela(Input& pInput,
|
|
LDSection& pSection,
|
|
llvm::StringRef pRegion) const;
|
|
|
|
/// readRel - read ELF rel and create Relocation
|
|
bool readRel(Input& pInput,
|
|
LDSection& pSection,
|
|
llvm::StringRef pRegion) const;
|
|
|
|
/// readDynamic - read ELF .dynamic in input dynobj
|
|
bool readDynamic(Input& pInput) const;
|
|
|
|
private:
|
|
struct AliasInfo {
|
|
LDSymbol* pt_alias; /// potential alias
|
|
uint64_t ld_value;
|
|
ResolveInfo::Binding ld_binding;
|
|
};
|
|
|
|
/// comparison function to sort symbols for analyzing weak alias.
|
|
/// sort symbols by symbol value and then weak before strong.
|
|
static bool less(AliasInfo p1, AliasInfo p2) {
|
|
if (p1.ld_value != p2.ld_value)
|
|
return (p1.ld_value < p2.ld_value);
|
|
if (p1.ld_binding != p2.ld_binding) {
|
|
if (ResolveInfo::Weak == p1.ld_binding)
|
|
return true;
|
|
else if (ResolveInfo::Weak == p2.ld_binding)
|
|
return false;
|
|
}
|
|
return p1.pt_alias->str() < p2.pt_alias->str();
|
|
}
|
|
};
|
|
|
|
/** \class ELFReader<64, true>
|
|
* \brief ELFReader<64, true> is a 64-bit, little endian ELFReader.
|
|
*/
|
|
template <>
|
|
class ELFReader<64, true> : public ELFReaderIF {
|
|
public:
|
|
typedef llvm::ELF::Elf64_Ehdr ELFHeader;
|
|
typedef llvm::ELF::Elf64_Shdr SectionHeader;
|
|
typedef llvm::ELF::Elf64_Sym Symbol;
|
|
typedef llvm::ELF::Elf64_Rel Rel;
|
|
typedef llvm::ELF::Elf64_Rela Rela;
|
|
|
|
public:
|
|
explicit ELFReader(GNULDBackend& pBackend);
|
|
|
|
~ELFReader();
|
|
|
|
/// ELFHeaderSize - return the size of the ELFHeader
|
|
size_t getELFHeaderSize() const { return sizeof(ELFHeader); }
|
|
|
|
/// isELF - is this a ELF file
|
|
bool isELF(const void* pELFHeader) const;
|
|
|
|
/// isMyEndian - is this ELF file in the same endian to me?
|
|
bool isMyEndian(const void* pELFHeader) const;
|
|
|
|
/// isMyMachine - is this ELF file generated for the same machine.
|
|
bool isMyMachine(const void* pELFHeader) const;
|
|
|
|
/// fileType - the file type of this file
|
|
Input::Type fileType(const void* pELFHeader) const;
|
|
|
|
/// readSectionHeaders - read ELF section header table and create LDSections
|
|
bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
|
|
|
|
/// readRegularSection - read a regular section and create fragments.
|
|
bool readRegularSection(Input& pInput, SectionData& pSD) const;
|
|
|
|
/// readSymbols - read ELF symbols and create LDSymbol
|
|
bool readSymbols(Input& pInput,
|
|
IRBuilder& pBuilder,
|
|
llvm::StringRef pRegion,
|
|
const char* StrTab) const;
|
|
|
|
/// readSignature - read a symbol from the given Input and index in symtab
|
|
/// This is used to get the signature of a group section.
|
|
ResolveInfo* readSignature(Input& pInput,
|
|
LDSection& pSymTab,
|
|
uint32_t pSymIdx) const;
|
|
|
|
/// readRela - read ELF rela and create Relocation
|
|
bool readRela(Input& pInput,
|
|
LDSection& pSection,
|
|
llvm::StringRef pRegion) const;
|
|
|
|
/// readRel - read ELF rel and create Relocation
|
|
bool readRel(Input& pInput,
|
|
LDSection& pSection,
|
|
llvm::StringRef pRegion) const;
|
|
|
|
/// readDynamic - read ELF .dynamic in input dynobj
|
|
bool readDynamic(Input& pInput) const;
|
|
|
|
private:
|
|
struct AliasInfo {
|
|
LDSymbol* pt_alias; /// potential alias
|
|
uint64_t ld_value;
|
|
ResolveInfo::Binding ld_binding;
|
|
};
|
|
|
|
/// comparison function to sort symbols for analyzing weak alias.
|
|
/// sort symbols by symbol value and then weak before strong.
|
|
static bool less(AliasInfo p1, AliasInfo p2) {
|
|
if (p1.ld_value != p2.ld_value)
|
|
return (p1.ld_value < p2.ld_value);
|
|
if (p1.ld_binding != p2.ld_binding) {
|
|
if (ResolveInfo::Weak == p1.ld_binding)
|
|
return true;
|
|
else if (ResolveInfo::Weak == p2.ld_binding)
|
|
return false;
|
|
}
|
|
return p1.pt_alias->str() < p2.pt_alias->str();
|
|
}
|
|
};
|
|
|
|
} // namespace mcld
|
|
|
|
#endif // MCLD_LD_ELFREADER_H_
|