| //===- FragmentLinker.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_FRAGMENT_FRAGMENT_LINKER_H |
| #define MCLD_FRAGMENT_FRAGMENT_LINKER_H |
| #ifdef ENABLE_UNITTEST |
| #include <gtest.h> |
| #endif |
| |
| #include <string> |
| |
| #include <mcld/LinkerConfig.h> |
| #include <mcld/LD/LDFileFormat.h> |
| #include <mcld/LD/LDSymbol.h> |
| #include <mcld/Fragment/Relocation.h> |
| #include <mcld/MC/MCLDInput.h> |
| |
| namespace mcld { |
| |
| class Module; |
| class TargetLDBackend; |
| class LinkerConfig; |
| class LDSection; |
| class LDSectionFactory; |
| class SectionData; |
| class Output; |
| class EhFrame; |
| class EhFrameHdr; |
| class MemoryArea; |
| class RelocData; |
| |
| /** \class FragmentLinker |
| * \brief FragmentLinker provides a pass to link object files. |
| */ |
| class FragmentLinker |
| { |
| public: |
| enum DefinePolicy |
| { |
| Force, |
| AsRefered |
| }; |
| |
| enum ResolvePolicy |
| { |
| Unresolve, |
| Resolve |
| }; |
| |
| public: |
| FragmentLinker(const LinkerConfig& pConfig, |
| Module& pModule, |
| TargetLDBackend& pBackend); |
| |
| ~FragmentLinker(); |
| |
| // ----- 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(); |
| |
| // ----- relocations ----- // |
| /// addRelocation - add a relocation entry in FragmentLinker (only for object file) |
| /// @param pType - the type of the relocation |
| /// @param pSym - the symbol should be the symbol in the input file. FragmentLinker |
| /// computes the real applied address by the output symbol. |
| /// @param pSection - the input relocation section |
| /// @param pOffset - the offset of target section. |
| /// @param pAddend - the addend value for applying relocation |
| Relocation* addRelocation(Relocation::Type pType, |
| LDSymbol& pSym, |
| LDSection& pSection, |
| uint32_t pOffset, |
| 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(MemoryArea& pOutput); |
| |
| // ----- capacity ----- // |
| const LinkerConfig& getLDInfo() const { return m_Config; } |
| |
| // ----- output attribute ----- // |
| /// isOutputPIC - return whether the output is position-independent |
| bool isOutputPIC() const; |
| |
| /// isStaticLink - return whether we're doing static link |
| bool isStaticLink() const; |
| |
| 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); |
| |
| /// checkIsOutputPIC - return whether the output is position-independent, |
| /// called by isOutputPIC() |
| bool checkIsOutputPIC() const; |
| |
| /// checkIsStaticLink - return whether we're doing static link, called by |
| /// isStaticLink() |
| bool checkIsStaticLink() const; |
| |
| /// normalSyncRelocationResult - sync relocation result when producing shared |
| /// objects or executables |
| void normalSyncRelocationResult(MemoryArea& pOutput); |
| |
| /// partialSyncRelocationResult - sync relocation result when doing partial |
| /// link |
| void partialSyncRelocationResult(MemoryArea& pOutput); |
| |
| /// writeRelocationResult - helper function of syncRelocationResult, write |
| /// relocation target data to output |
| void writeRelocationResult(Relocation& pReloc, uint8_t* pOutput); |
| |
| private: |
| const LinkerConfig& m_Config; |
| Module& m_Module; |
| TargetLDBackend& m_Backend; |
| }; |
| |
| #include "FragmentLinker.tcc" |
| |
| } // namespace of mcld |
| |
| #endif |
| |