//===- 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