//===- ResolveInfo.h ------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_LD_RESOLVEINFO_H_ #define MCLD_LD_RESOLVEINFO_H_ #include #include namespace mcld { class LDSymbol; class LinkerConfig; /** \class ResolveInfo * \brief ResolveInfo records the information about how to resolve a symbol. * * A symbol must have some `attributes': * - Desc - Defined, Reference, Common or Indirect * - Binding - Global, Local, Weak * - IsDyn - appear in dynamic objects or regular objects * - Type - what the symbol refers to * - Size - the size of the symbol point to * - Value - the pointer to another LDSymbol * In order to save the memory and speed up the performance, FragmentLinker *uses * a bit field to store all attributes. * * The maximum string length is (2^16 - 1) */ class ResolveInfo { friend class FragmentLinker; friend class IRBuilder; public: typedef uint64_t SizeType; /** \enum Type * \brief What the symbol stand for * * It is like ELF32_ST_TYPE * MachO does not need this, and can not jump between Thumb and ARM code. */ enum Type { NoType = 0, Object = 1, Function = 2, Section = 3, File = 4, CommonBlock = 5, ThreadLocal = 6, IndirectFunc = 10, LoProc = 13, HiProc = 15 }; /** \enum Desc * \brief Description of the symbols. * * Follow the naming in MachO. Like MachO nlist::n_desc * In ELF, is a part of st_shndx */ enum Desc { Undefined = 0, Define = 1, Common = 2, Indirect = 3, NoneDesc }; enum Binding { Global = 0, Weak = 1, Local = 2, Absolute = 3, NoneBinding }; enum Visibility { Default = 0, Internal = 1, Hidden = 2, Protected = 3 }; // ----- For HashTable ----- // typedef llvm::StringRef key_type; public: // ----- factory method ----- // static ResolveInfo* Create(const key_type& pKey); static void Destroy(ResolveInfo*& pInfo); static ResolveInfo* Null(); // ----- modifiers ----- // /// setRegular - set the source of the file is a regular object void setRegular(); /// setDynamic - set the source of the file is a dynamic object void setDynamic(); /// setSource - set the source of the file /// @param pIsDyn is the source from a dynamic object? void setSource(bool pIsDyn); void setType(uint32_t pType); void setDesc(uint32_t pDesc); void setBinding(uint32_t pBinding); void setOther(uint32_t pOther); void setVisibility(Visibility pVisibility); void setIsSymbol(bool pIsSymbol); void setReserved(uint32_t pReserved); void setSize(SizeType pSize) { m_Size = pSize; } void override(const ResolveInfo& pForm); void overrideAttributes(const ResolveInfo& pFrom); void overrideVisibility(const ResolveInfo& pFrom); void setSymPtr(const LDSymbol* pSymPtr) { m_Ptr.sym_ptr = const_cast(pSymPtr); } void setLink(const ResolveInfo* pTarget) { m_Ptr.info_ptr = const_cast(pTarget); m_BitField |= indirect_flag; } /// setInDyn - set if the symbol has been seen in the dynamic objects. Once /// InDyn set, then it won't be set back to false void setInDyn(); // ----- observers ----- // bool isNull() const; bool isSymbol() const; bool isString() const; bool isGlobal() const; bool isWeak() const; bool isLocal() const; bool isAbsolute() const; bool isDefine() const; bool isUndef() const; bool isDyn() const; bool isCommon() const; bool isIndirect() const; bool isInDyn() const; uint32_t type() const; uint32_t desc() const; uint32_t binding() const; uint32_t reserved() const; uint8_t other() const { return (uint8_t)visibility(); } Visibility visibility() const; LDSymbol* outSymbol() { return m_Ptr.sym_ptr; } const LDSymbol* outSymbol() const { return m_Ptr.sym_ptr; } ResolveInfo* link() { return m_Ptr.info_ptr; } const ResolveInfo* link() const { return m_Ptr.info_ptr; } SizeType size() const { return m_Size; } const char* name() const { return m_Name; } unsigned int nameSize() const { return (m_BitField >> NAME_LENGTH_OFFSET); } uint32_t info() const { return (m_BitField & INFO_MASK); } uint32_t bitfield() const { return m_BitField; } // shouldForceLocal - check if this symbol should be forced to local bool shouldForceLocal(const LinkerConfig& pConfig); // ----- For HashTable ----- // bool compare(const key_type& pKey); private: static const uint32_t GLOBAL_OFFSET = 0; static const uint32_t GLOBAL_MASK = 1; static const uint32_t DYN_OFFSET = 1; static const uint32_t DYN_MASK = 1 << DYN_OFFSET; static const uint32_t DESC_OFFSET = 2; static const uint32_t DESC_MASK = 0x3 << DESC_OFFSET; static const uint32_t LOCAL_OFFSET = 4; static const uint32_t LOCAL_MASK = 1 << LOCAL_OFFSET; static const uint32_t BINDING_MASK = GLOBAL_MASK | LOCAL_MASK; static const uint32_t VISIBILITY_OFFSET = 5; static const uint32_t VISIBILITY_MASK = 0x3 << VISIBILITY_OFFSET; static const uint32_t TYPE_OFFSET = 7; static const uint32_t TYPE_MASK = 0xF << TYPE_OFFSET; static const uint32_t SYMBOL_OFFSET = 11; static const uint32_t SYMBOL_MASK = 1 << SYMBOL_OFFSET; static const uint32_t RESERVED_OFFSET = 12; static const uint32_t RESERVED_MASK = 0xF << RESERVED_OFFSET; static const uint32_t IN_DYN_OFFSET = 16; static const uint32_t IN_DYN_MASK = 1 << IN_DYN_OFFSET; static const uint32_t NAME_LENGTH_OFFSET = 17; static const uint32_t INFO_MASK = 0xF; static const uint32_t RESOLVE_MASK = 0xFFFF; union SymOrInfo { LDSymbol* sym_ptr; ResolveInfo* info_ptr; }; public: static const uint32_t global_flag = 0 << GLOBAL_OFFSET; static const uint32_t weak_flag = 1 << GLOBAL_OFFSET; static const uint32_t regular_flag = 0 << DYN_OFFSET; static const uint32_t dynamic_flag = 1 << DYN_OFFSET; static const uint32_t undefine_flag = 0 << DESC_OFFSET; static const uint32_t define_flag = 1 << DESC_OFFSET; static const uint32_t common_flag = 2 << DESC_OFFSET; static const uint32_t indirect_flag = 3 << DESC_OFFSET; static const uint32_t local_flag = 1 << LOCAL_OFFSET; static const uint32_t absolute_flag = BINDING_MASK; static const uint32_t object_flag = Object << TYPE_OFFSET; static const uint32_t function_flag = Function << TYPE_OFFSET; static const uint32_t section_flag = Section << TYPE_OFFSET; static const uint32_t file_flag = File << TYPE_OFFSET; static const uint32_t string_flag = 0 << SYMBOL_OFFSET; static const uint32_t symbol_flag = 1 << SYMBOL_OFFSET; static const uint32_t indyn_flag = 1 << IN_DYN_OFFSET; private: ResolveInfo(); ResolveInfo(const ResolveInfo& pCopy); ResolveInfo& operator=(const ResolveInfo& pCopy); ~ResolveInfo(); private: SizeType m_Size; SymOrInfo m_Ptr; /** m_BitField * 31 ... 17 16 15 12 11 10..7 6 .. 5 4 3 2 * 1 0 * |length of m_Name|InDyn|reserved|Symbol|Type |ELF * visibility|Local|Com|Def|Dyn|Weak| */ uint32_t m_BitField; char m_Name[]; }; } // namespace mcld #endif // MCLD_LD_RESOLVEINFO_H_