//===- ELFDynamic.h -------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_TARGET_ELFDYNAMIC_H
#define MCLD_TARGET_ELFDYNAMIC_H
#include <mcld/LD/LDSection.h>
#include <mcld/Support/FileOutputBuffer.h>
#include <llvm/Support/ELF.h>
#include <vector>
#include <cstring>
namespace mcld {
class ELFFileFormat;
class GNULDBackend;
class LinkerConfig;
namespace elf_dynamic {
/** \class EntryIF
* \brief EntryIF provides a common interface for one entry in the dynamic
* section
*/
class EntryIF
{
protected:
EntryIF();
public:
virtual ~EntryIF();
virtual EntryIF* clone() const = 0;
virtual size_t size() const = 0;
virtual size_t symbolSize() const = 0;
virtual size_t relSize() const = 0;
virtual size_t relaSize() const = 0;
virtual size_t emit(uint8_t* pAddress) const = 0;
virtual void setValue(uint64_t pTag, uint64_t pValue) = 0;
};
template<size_t BITNUMBER, bool LITTLEENDIAN>
class Entry
{ };
template<>
class Entry<32, true> : public EntryIF
{
public:
typedef llvm::ELF::Elf32_Dyn Pair;
typedef llvm::ELF::Elf32_Sym Symbol;
typedef llvm::ELF::Elf32_Rel Rel;
typedef llvm::ELF::Elf32_Rela Rela;
public:
inline Entry();
inline ~Entry();
Entry* clone() const
{ return new Entry(); }
size_t size() const
{ return sizeof(Pair); }
size_t symbolSize() const
{ return sizeof(Symbol); }
size_t relSize() const
{ return sizeof(Rel); }
size_t relaSize() const
{ return sizeof(Rela); }
inline void setValue(uint64_t pTag, uint64_t pValue);
inline size_t emit(uint8_t* pAddress) const;
private:
Pair m_Pair;
};
template<>
class Entry<64, true> : public EntryIF
{
public:
typedef llvm::ELF::Elf64_Dyn Pair;
typedef llvm::ELF::Elf64_Sym Symbol;
typedef llvm::ELF::Elf64_Rel Rel;
typedef llvm::ELF::Elf64_Rela Rela;
public:
inline Entry();
inline ~Entry();
Entry* clone() const
{ return new Entry(); }
size_t size() const
{ return sizeof(Pair); }
size_t symbolSize() const
{ return sizeof(Symbol); }
size_t relSize() const
{ return sizeof(Rel); }
size_t relaSize() const
{ return sizeof(Rela); }
inline void setValue(uint64_t pTag, uint64_t pValue);
inline size_t emit(uint8_t* pAddress) const;
private:
Pair m_Pair;
};
#include "ELFDynamic.tcc"
} // namespace of elf_dynamic
/** \class ELFDynamic
* \brief ELFDynamic is the .dynamic section in ELF shared and executable
* files.
*/
class ELFDynamic
{
public:
typedef std::vector<elf_dynamic::EntryIF*> EntryListType;
typedef EntryListType::iterator iterator;
typedef EntryListType::const_iterator const_iterator;
public:
ELFDynamic(const GNULDBackend& pBackend, const LinkerConfig& pConfig);
virtual ~ELFDynamic();
size_t size() const;
size_t entrySize() const;
size_t numOfBytes() const;
/// reserveEntries - reserve entries
void reserveEntries(const ELFFileFormat& pFormat);
/// reserveNeedEntry - reserve on DT_NEED entry.
void reserveNeedEntry();
/// applyEntries - apply entries
void applyEntries(const ELFFileFormat& pFormat);
void applySoname(uint64_t pStrTabIdx);
const_iterator needBegin() const { return m_NeedList.begin(); }
iterator needBegin() { return m_NeedList.begin(); }
const_iterator needEnd() const { return m_NeedList.end(); }
iterator needEnd() { return m_NeedList.end(); }
/// emit
void emit(const LDSection& pSection, MemoryRegion& pRegion) const;
protected:
/// reserveTargetEntries - reserve target dependent entries
virtual void reserveTargetEntries(const ELFFileFormat& pFormat) = 0;
/// applyTargetEntries - apply target-dependant
virtual void applyTargetEntries(const ELFFileFormat& pFormat) = 0;
protected:
void reserveOne(uint64_t pTag);
void applyOne(uint64_t pTag, uint64_t pValue);
size_t symbolSize() const;
const LinkerConfig& config() const { return m_Config; }
private:
EntryListType m_EntryList;
EntryListType m_NeedList;
elf_dynamic::EntryIF* m_pEntryFactory;
const GNULDBackend& m_Backend;
const LinkerConfig& m_Config;
// The entry reserved and the entry being applied are not must matched.
// For better performance, we use a simple counter and apply entry one-by-one
// by the counter. m_Idx is the counter indicating to the entry being applied.
size_t m_Idx;
};
} // namespace of mcld
#endif