| //===- ResolveInfo.cpp ----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/LD/ResolveInfo.h" |
| |
| #include "mcld/LinkerConfig.h" |
| #include "mcld/LD/LDSection.h" |
| #include "mcld/Support/GCFactory.h" |
| |
| #include <llvm/Support/ManagedStatic.h> |
| |
| #include <cstdlib> |
| #include <cstring> |
| |
| 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 | VISIBILITY_MASK; |
| m_BitField |= (pFrom.m_BitField & (RESOLVE_MASK & ~VISIBILITY_MASK)); |
| } |
| |
| /// overrideVisibility - override the visibility |
| /// always use the most strict visibility |
| void ResolveInfo::overrideVisibility(const ResolveInfo& pFrom) { |
| // 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 (from_vis != 0) { |
| if (cur_vis == 0) |
| 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<ResolveInfo::Visibility>(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<ResolveInfo::Visibility>((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 (std::memcmp(m_Name, pKey.data(), length) == 0); |
| } |
| |
| 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<ResolveInfo*>(malloc(sizeof(ResolveInfo) + pKey.size() + 1)); |
| if (info == NULL) |
| 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 (pInfo != NULL) { |
| pInfo->~ResolveInfo(); |
| free(pInfo); |
| } |
| |
| pInfo = NULL; |
| } |
| |
| ResolveInfo* ResolveInfo::Null() { |
| if (g_NullResolveInfo == NULL) { |
| g_NullResolveInfo = |
| static_cast<ResolveInfo*>(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; |
| } |
| |
| } // namespace mcld |