//===- ResolveInfo.cpp ----------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include #include #include #include #include #include using namespace mcld; /// g_NullResolveInfo - a pointer to Null ResolveInfo. static ResolveInfo* g_NullResolveInfo = NULL; //===----------------------------------------------------------------------===// // ResolveInfo //===----------------------------------------------------------------------===// ResolveInfo::ResolveInfo() : m_Size(0), m_BitField(0) { m_Ptr.sym_ptr = 0; } ResolveInfo::~ResolveInfo() { } void ResolveInfo::override(const ResolveInfo& pFrom) { m_Size = pFrom.m_Size; overrideAttributes(pFrom); overrideVisibility(pFrom); } void ResolveInfo::overrideAttributes(const ResolveInfo& pFrom) { m_BitField &= ~RESOLVE_MASK; m_BitField |= (pFrom.m_BitField & RESOLVE_MASK); } /// overrideVisibility - override the visibility /// always use the most strict visibility void ResolveInfo::overrideVisibility(const ResolveInfo& pFrom) { // Reference: Google gold linker: resolve.cc // // The rule for combining visibility is that we always choose the // most constrained visibility. In order of increasing constraint, // visibility goes PROTECTED, HIDDEN, INTERNAL. This is the reverse // of the numeric values, so the effect is that we always want the // smallest non-zero value. // // enum { // STV_DEFAULT = 0, // STV_INTERNAL = 1, // STV_HIDDEN = 2, // STV_PROTECTED = 3 // }; Visibility from_vis = pFrom.visibility(); Visibility cur_vis = visibility(); if (0 != from_vis ) { if (0 == cur_vis) setVisibility(from_vis); else if (cur_vis > from_vis) setVisibility(from_vis); } } void ResolveInfo::setRegular() { m_BitField &= (~dynamic_flag); } void ResolveInfo::setDynamic() { m_BitField |= dynamic_flag; } void ResolveInfo::setSource(bool pIsDyn) { if (pIsDyn) m_BitField |= dynamic_flag; else m_BitField &= (~dynamic_flag); } void ResolveInfo::setInDyn() { m_BitField |= indyn_flag; } void ResolveInfo::setType(uint32_t pType) { m_BitField &= ~TYPE_MASK; m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK); } void ResolveInfo::setDesc(uint32_t pDesc) { m_BitField &= ~DESC_MASK; m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK); } void ResolveInfo::setBinding(uint32_t pBinding) { m_BitField &= ~BINDING_MASK; if (pBinding == Local || pBinding == Absolute) m_BitField |= local_flag; if (pBinding == Weak || pBinding == Absolute) m_BitField |= weak_flag; } void ResolveInfo::setReserved(uint32_t pReserved) { m_BitField &= ~RESERVED_MASK; m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK); } void ResolveInfo::setOther(uint32_t pOther) { setVisibility(static_cast(pOther & 0x3)); } void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility) { m_BitField &= ~VISIBILITY_MASK; m_BitField |= pVisibility << VISIBILITY_OFFSET; } void ResolveInfo::setIsSymbol(bool pIsSymbol) { if (pIsSymbol) m_BitField |= symbol_flag; else m_BitField &= ~symbol_flag; } bool ResolveInfo::isNull() const { return (this == Null()); } bool ResolveInfo::isDyn() const { return (dynamic_flag == (m_BitField & DYN_MASK)); } bool ResolveInfo::isUndef() const { return (undefine_flag == (m_BitField & DESC_MASK)); } bool ResolveInfo::isDefine() const { return (define_flag == (m_BitField & DESC_MASK)); } bool ResolveInfo::isCommon() const { return (common_flag == (m_BitField & DESC_MASK)); } bool ResolveInfo::isIndirect() const { return (indirect_flag == (m_BitField & DESC_MASK)); } // isGlobal - [L,W] == [0, 0] bool ResolveInfo::isGlobal() const { return (global_flag == (m_BitField & BINDING_MASK)); } // isWeak - [L,W] == [0, 1] bool ResolveInfo::isWeak() const { return (weak_flag == (m_BitField & BINDING_MASK)); } // isLocal - [L,W] == [1, 0] bool ResolveInfo::isLocal() const { return (local_flag == (m_BitField & BINDING_MASK)); } // isAbsolute - [L,W] == [1, 1] bool ResolveInfo::isAbsolute() const { return (absolute_flag == (m_BitField & BINDING_MASK)); } bool ResolveInfo::isSymbol() const { return (symbol_flag == (m_BitField & SYMBOL_MASK)); } bool ResolveInfo::isString() const { return (string_flag == (m_BitField & SYMBOL_MASK)); } bool ResolveInfo::isInDyn() const { return (indyn_flag == (m_BitField & IN_DYN_MASK)); } uint32_t ResolveInfo::type() const { return (m_BitField & TYPE_MASK) >> TYPE_OFFSET; } uint32_t ResolveInfo::desc() const { return (m_BitField & DESC_MASK) >> DESC_OFFSET; } uint32_t ResolveInfo::binding() const { if (m_BitField & LOCAL_MASK) { if (m_BitField & GLOBAL_MASK) { return ResolveInfo::Absolute; } return ResolveInfo::Local; } return m_BitField & GLOBAL_MASK; } uint32_t ResolveInfo::reserved() const { return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET; } ResolveInfo::Visibility ResolveInfo::visibility() const { return static_cast((m_BitField & VISIBILITY_MASK) >> VISIBILITY_OFFSET); } bool ResolveInfo::compare(const ResolveInfo::key_type& pKey) { size_t length = nameSize(); if (length != pKey.size()) return false; return (0 == std::memcmp(m_Name, pKey.data(), length)); } bool ResolveInfo::shouldForceLocal(const LinkerConfig& pConfig) { // forced local symbol matches all rules: // 1. We are not doing incremental linking. // 2. The symbol is with Hidden or Internal visibility. // 3. The symbol should be global or weak. Otherwise, local symbol is local. // 4. The symbol is defined or common if (LinkerConfig::Object != pConfig.codeGenType() && (visibility() == ResolveInfo::Hidden || visibility() == ResolveInfo::Internal) && (isGlobal() || isWeak()) && (isDefine() || isCommon())) return true; return false; } //===----------------------------------------------------------------------===// // ResolveInfo Factory Methods //===----------------------------------------------------------------------===// ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey) { ResolveInfo* info = static_cast( malloc(sizeof(ResolveInfo)+pKey.size()+1)); if (NULL == info) return NULL; new (info) ResolveInfo(); // call constructor at the `result` address. std::memcpy(info->m_Name, pKey.data(), pKey.size()); info->m_Name[pKey.size()] = '\0'; info->m_BitField &= ~ResolveInfo::RESOLVE_MASK; info->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET); return info; } void ResolveInfo::Destroy(ResolveInfo*& pInfo) { if (pInfo->isNull()) return; if (NULL != pInfo) { pInfo->~ResolveInfo(); free(pInfo); } pInfo = NULL; } ResolveInfo* ResolveInfo::Null() { if (NULL == g_NullResolveInfo) { g_NullResolveInfo = static_cast( malloc(sizeof(ResolveInfo) + 1)); new (g_NullResolveInfo) ResolveInfo(); g_NullResolveInfo->m_Name[0] = '\0'; g_NullResolveInfo->m_BitField = 0x0; g_NullResolveInfo->setBinding(Local); } return g_NullResolveInfo; }