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