You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
4.5 KiB
188 lines
4.5 KiB
//===- 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 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 mcld
|
|
|
|
#endif // MCLD_TARGET_ELFDYNAMIC_H_
|