1//===- ResolveInfo.cpp ----------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include "mcld/LD/ResolveInfo.h" 10 11#include "mcld/LinkerConfig.h" 12#include "mcld/LD/LDSection.h" 13#include "mcld/Support/GCFactory.h" 14 15#include <llvm/Support/ManagedStatic.h> 16 17#include <cstdlib> 18#include <cstring> 19 20namespace mcld { 21 22/// g_NullResolveInfo - a pointer to Null ResolveInfo. 23static ResolveInfo* g_NullResolveInfo = NULL; 24 25//===----------------------------------------------------------------------===// 26// ResolveInfo 27//===----------------------------------------------------------------------===// 28ResolveInfo::ResolveInfo() : m_Size(0), m_BitField(0) { 29 m_Ptr.sym_ptr = 0; 30} 31 32ResolveInfo::~ResolveInfo() { 33} 34 35void ResolveInfo::override(const ResolveInfo& pFrom) { 36 m_Size = pFrom.m_Size; 37 overrideAttributes(pFrom); 38 overrideVisibility(pFrom); 39} 40 41void ResolveInfo::overrideAttributes(const ResolveInfo& pFrom) { 42 m_BitField &= ~RESOLVE_MASK | VISIBILITY_MASK; 43 m_BitField |= (pFrom.m_BitField & (RESOLVE_MASK & ~VISIBILITY_MASK)); 44} 45 46/// overrideVisibility - override the visibility 47/// always use the most strict visibility 48void ResolveInfo::overrideVisibility(const ResolveInfo& pFrom) { 49 // The rule for combining visibility is that we always choose the 50 // most constrained visibility. In order of increasing constraint, 51 // visibility goes PROTECTED, HIDDEN, INTERNAL. This is the reverse 52 // of the numeric values, so the effect is that we always want the 53 // smallest non-zero value. 54 // 55 // enum { 56 // STV_DEFAULT = 0, 57 // STV_INTERNAL = 1, 58 // STV_HIDDEN = 2, 59 // STV_PROTECTED = 3 60 // }; 61 62 Visibility from_vis = pFrom.visibility(); 63 Visibility cur_vis = visibility(); 64 if (from_vis != 0) { 65 if (cur_vis == 0) 66 setVisibility(from_vis); 67 else if (cur_vis > from_vis) 68 setVisibility(from_vis); 69 } 70} 71 72void ResolveInfo::setRegular() { 73 m_BitField &= (~dynamic_flag); 74} 75 76void ResolveInfo::setDynamic() { 77 m_BitField |= dynamic_flag; 78} 79 80void ResolveInfo::setSource(bool pIsDyn) { 81 if (pIsDyn) 82 m_BitField |= dynamic_flag; 83 else 84 m_BitField &= (~dynamic_flag); 85} 86 87void ResolveInfo::setInDyn() { 88 m_BitField |= indyn_flag; 89} 90 91void ResolveInfo::setType(uint32_t pType) { 92 m_BitField &= ~TYPE_MASK; 93 m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK); 94} 95 96void ResolveInfo::setDesc(uint32_t pDesc) { 97 m_BitField &= ~DESC_MASK; 98 m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK); 99} 100 101void ResolveInfo::setBinding(uint32_t pBinding) { 102 m_BitField &= ~BINDING_MASK; 103 if (pBinding == Local || pBinding == Absolute) 104 m_BitField |= local_flag; 105 if (pBinding == Weak || pBinding == Absolute) 106 m_BitField |= weak_flag; 107} 108 109void ResolveInfo::setReserved(uint32_t pReserved) { 110 m_BitField &= ~RESERVED_MASK; 111 m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK); 112} 113 114void ResolveInfo::setOther(uint32_t pOther) { 115 setVisibility(static_cast<ResolveInfo::Visibility>(pOther & 0x3)); 116} 117 118void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility) { 119 m_BitField &= ~VISIBILITY_MASK; 120 m_BitField |= pVisibility << VISIBILITY_OFFSET; 121} 122 123void ResolveInfo::setIsSymbol(bool pIsSymbol) { 124 if (pIsSymbol) 125 m_BitField |= symbol_flag; 126 else 127 m_BitField &= ~symbol_flag; 128} 129 130bool ResolveInfo::isNull() const { 131 return (this == Null()); 132} 133 134bool ResolveInfo::isDyn() const { 135 return (dynamic_flag == (m_BitField & DYN_MASK)); 136} 137 138bool ResolveInfo::isUndef() const { 139 return (undefine_flag == (m_BitField & DESC_MASK)); 140} 141 142bool ResolveInfo::isDefine() const { 143 return (define_flag == (m_BitField & DESC_MASK)); 144} 145 146bool ResolveInfo::isCommon() const { 147 return (common_flag == (m_BitField & DESC_MASK)); 148} 149 150bool ResolveInfo::isIndirect() const { 151 return (indirect_flag == (m_BitField & DESC_MASK)); 152} 153 154// isGlobal - [L,W] == [0, 0] 155bool ResolveInfo::isGlobal() const { 156 return (global_flag == (m_BitField & BINDING_MASK)); 157} 158 159// isWeak - [L,W] == [0, 1] 160bool ResolveInfo::isWeak() const { 161 return (weak_flag == (m_BitField & BINDING_MASK)); 162} 163 164// isLocal - [L,W] == [1, 0] 165bool ResolveInfo::isLocal() const { 166 return (local_flag == (m_BitField & BINDING_MASK)); 167} 168 169// isAbsolute - [L,W] == [1, 1] 170bool ResolveInfo::isAbsolute() const { 171 return (absolute_flag == (m_BitField & BINDING_MASK)); 172} 173 174bool ResolveInfo::isSymbol() const { 175 return (symbol_flag == (m_BitField & SYMBOL_MASK)); 176} 177 178bool ResolveInfo::isString() const { 179 return (string_flag == (m_BitField & SYMBOL_MASK)); 180} 181 182bool ResolveInfo::isInDyn() const { 183 return (indyn_flag == (m_BitField & IN_DYN_MASK)); 184} 185 186uint32_t ResolveInfo::type() const { 187 return (m_BitField & TYPE_MASK) >> TYPE_OFFSET; 188} 189 190uint32_t ResolveInfo::desc() const { 191 return (m_BitField & DESC_MASK) >> DESC_OFFSET; 192} 193 194uint32_t ResolveInfo::binding() const { 195 if (m_BitField & LOCAL_MASK) { 196 if (m_BitField & GLOBAL_MASK) { 197 return ResolveInfo::Absolute; 198 } 199 return ResolveInfo::Local; 200 } 201 return m_BitField & GLOBAL_MASK; 202} 203 204uint32_t ResolveInfo::reserved() const { 205 return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET; 206} 207 208ResolveInfo::Visibility ResolveInfo::visibility() const { 209 return static_cast<ResolveInfo::Visibility>((m_BitField & VISIBILITY_MASK) >> 210 VISIBILITY_OFFSET); 211} 212 213bool ResolveInfo::compare(const ResolveInfo::key_type& pKey) { 214 size_t length = nameSize(); 215 if (length != pKey.size()) 216 return false; 217 return (std::memcmp(m_Name, pKey.data(), length) == 0); 218} 219 220bool ResolveInfo::shouldForceLocal(const LinkerConfig& pConfig) { 221 // forced local symbol matches all rules: 222 // 1. We are not doing incremental linking. 223 // 2. The symbol is with Hidden or Internal visibility. 224 // 3. The symbol should be global or weak. Otherwise, local symbol is local. 225 // 4. The symbol is defined or common 226 if (LinkerConfig::Object != pConfig.codeGenType() && 227 (visibility() == ResolveInfo::Hidden || 228 visibility() == ResolveInfo::Internal) && 229 (isGlobal() || isWeak()) && (isDefine() || isCommon())) 230 return true; 231 return false; 232} 233//===----------------------------------------------------------------------===// 234// ResolveInfo Factory Methods 235//===----------------------------------------------------------------------===// 236ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey) { 237 ResolveInfo* info = 238 static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + pKey.size() + 1)); 239 if (info == NULL) 240 return NULL; 241 242 new (info) ResolveInfo(); // call constructor at the `result` address. 243 std::memcpy(info->m_Name, pKey.data(), pKey.size()); 244 info->m_Name[pKey.size()] = '\0'; 245 info->m_BitField &= ~ResolveInfo::RESOLVE_MASK; 246 info->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET); 247 return info; 248} 249 250void ResolveInfo::Destroy(ResolveInfo*& pInfo) { 251 if (pInfo->isNull()) 252 return; 253 254 if (pInfo != NULL) { 255 pInfo->~ResolveInfo(); 256 free(pInfo); 257 } 258 259 pInfo = NULL; 260} 261 262ResolveInfo* ResolveInfo::Null() { 263 if (g_NullResolveInfo == NULL) { 264 g_NullResolveInfo = 265 static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + 1)); 266 new (g_NullResolveInfo) ResolveInfo(); 267 g_NullResolveInfo->m_Name[0] = '\0'; 268 g_NullResolveInfo->m_BitField = 0x0; 269 g_NullResolveInfo->setBinding(Local); 270 } 271 return g_NullResolveInfo; 272} 273 274} // namespace mcld 275