//===- MCLinker.h -------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a number of APIs used by SectLinker.
// These APIs do the things which a linker should do.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_MCLINKER_H
#define MCLD_MCLINKER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <set>
#include <string>
#include <llvm/ADT/ilist.h>
#include <mcld/LD/StaticResolver.h>
#include <mcld/LD/LDSectionFactory.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/Relocation.h>
#include <mcld/LD/SectionMerger.h>
#include <mcld/LD/Layout.h>
#include <mcld/MC/MCLDInput.h>
#include <mcld/MC/SymbolCategory.h>
#include <mcld/Support/GCFactory.h>
#include <mcld/Support/GCFactoryListTraits.h>
namespace mcld {
class TargetLDBackend;
class MCLDInfo;
class LDSection;
class LDSectionFactory;
class SectionData;
class SectionMap;
class Output;
class EhFrame;
class EhFrameHdr;
/** \class MCLinker
* \brief MCLinker provides a pass to link object files.
*/
class MCLinker
{
public:
enum DefinePolicy
{
Force,
AsRefered
};
enum ResolvePolicy
{
Unresolve,
Resolve
};
public:
MCLinker(TargetLDBackend& pBackend,
MCLDInfo& pLDInfo,
SectionMap& pSectionMap);
~MCLinker();
// ----- about symbols ----- //
/// addDynSymbol - add a symbol and resolve it immediately
template<Input::Type FROM>
LDSymbol* addSymbol(const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
/// defineSymbol - add a symbol
/// defineSymbol define a output symbol
///
/// @tparam POLICY idicate how to define the symbol.
/// - Force
/// - Define the symbol forcefully. If the symbol has existed, override
/// it. Otherwise, define it.
/// - AsRefered
/// - If the symbol has existed, override it. Otherwise, return NULL
/// immediately.
///
/// @tparam RESOLVE indicate whether to resolve the symbol or not.
/// - Unresolve
/// - Do not resolve the symbol, and override the symbol immediately.
/// - Resolve
/// - Resolve the defined symbol.
///
/// @return If the output symbol has existed, return it. Otherwise, create
/// a new symbol and return the new one.
template<DefinePolicy POLICY, ResolvePolicy RESOLVE>
LDSymbol* defineSymbol(const llvm::StringRef& pName,
bool pIsDyn,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
bool finalizeSymbols();
// ----- sections ----- //
/// getSectionMap - getSectionMap to change the behavior of SectionMerger
/// SectionMap& getSectionMap()
/// { return m_SectionMap; }
/// createSectHdr - for reader and standard/target format to create a section
/// header. This function will create a new LDSection and return it. If the
/// output has no related LDSection, this function will also create one and
/// push into the output.
LDSection& createSectHdr(const std::string& pName,
LDFileFormat::Kind pKind,
uint32_t pType,
uint32_t pFlag);
/// getOrCreateOutputSectHdr - for reader and standard/target format to get
/// or create the output's section header
LDSection& getOrCreateOutputSectHdr(const std::string& pName,
LDFileFormat::Kind pKind,
uint32_t pType,
uint32_t pFlag,
uint32_t pAlign = 0x0);
/// getOrCreateSectData - for reader to map and perform section merging immediately
SectionData& getOrCreateSectData(LDSection& pSection);
// ----- eh_frame sections ----- //
/// addEhFrame - add an exception handling section
/// @param pInput - the Input contains this section
/// @param pSection - the input section
/// @param pArea - the memory area which pSection is within.
uint64_t addEhFrame(const Input& pInput,
LDSection& pSection,
MemoryArea& pArea);
// ----- relocations ----- //
/// addRelocation - add a relocation entry in MCLinker (only for object file)
/// @param pType - the type of the relocation
/// @param pResolveInfo - the symbol should be the symbol in the input file. MCLinker
/// computes the real applied address by the output symbol.
/// @param pFragmentRef - the fragment reference of the applied address.
/// @param pAddend - the addend value for applying relocation
Relocation* addRelocation(Relocation::Type pType,
const LDSymbol& pSym,
ResolveInfo& pResolveInfo,
FragmentRef& pFragmentRef,
const LDSection& pSection,
Relocation::Address pAddend = 0);
/// applyRelocations - apply all relocation enties.
bool applyRelocations();
/// syncRelocationResult - After applying relocation, write back relocation target
/// data to output file.
void syncRelocationResult();
// ----- layout ----- //
void initSectionMap();
Layout& getLayout()
{ return m_Layout; }
const Layout& getLayout() const
{ return m_Layout; }
bool layout();
// ----- output symbols ----- //
SymbolCategory& getOutputSymbols()
{ return m_OutputSymbols; }
const SymbolCategory& getOutputSymbols() const
{ return m_OutputSymbols; }
// ----- capacity ----- //
MCLDInfo& getLDInfo()
{ return m_LDInfo; }
const MCLDInfo& getLDInfo() const
{ return m_LDInfo; }
private:
LDSymbol* defineSymbolForcefully(const llvm::StringRef& pName,
bool pIsDyn,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
LDSymbol* defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
bool pIsDyn,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
LDSymbol* defineSymbolAsRefered(const llvm::StringRef& pName,
bool pIsDyn,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
LDSymbol* defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
bool pIsDyn,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
bool shouldForceLocal(const ResolveInfo& pInfo) const;
LDSymbol* addSymbolFromDynObj(const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
LDSymbol* addSymbolFromObject(const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
private:
typedef GCFactory<LDSymbol, 0> LDSymbolFactory;
typedef GCFactory<SectionData, 0> LDSectionDataFactory;
typedef llvm::iplist<Fragment,
GCFactoryListTraits<Fragment> > RelocationListType;
typedef std::set<LDSymbol*> ForceLocalSymbolTable;
typedef std::vector<LDSymbol*> OutputSymbolTable;
private:
TargetLDBackend& m_Backend;
MCLDInfo& m_LDInfo;
SectionMap& m_SectionMap;
LDSymbolFactory m_LDSymbolFactory;
LDSectionFactory m_LDSectHdrFactory;
LDSectionDataFactory m_LDSectDataFactory;
SectionMerger* m_pSectionMerger;
Layout m_Layout;
RelocationListType m_RelocationList;
SymbolCategory m_OutputSymbols;
};
#include "MCLinker.tcc"
} // namespace of mcld
#endif