• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //===----------------------------------------------------------------------===//
ResolveInfo()25 ResolveInfo::ResolveInfo()
26   : m_Size(0), m_BitField(0) {
27   m_Ptr.sym_ptr = 0;
28 }
29 
~ResolveInfo()30 ResolveInfo::~ResolveInfo()
31 {
32 }
33 
override(const ResolveInfo & pFrom)34 void ResolveInfo::override(const ResolveInfo& pFrom)
35 {
36   m_Size = pFrom.m_Size;
37   overrideAttributes(pFrom);
38   overrideVisibility(pFrom);
39 }
40 
overrideAttributes(const ResolveInfo & pFrom)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
overrideVisibility(const ResolveInfo & pFrom)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 
setRegular()76 void ResolveInfo::setRegular()
77 {
78   m_BitField &= (~dynamic_flag);
79 }
80 
setDynamic()81 void ResolveInfo::setDynamic()
82 {
83   m_BitField |= dynamic_flag;
84 }
85 
setSource(bool pIsDyn)86 void ResolveInfo::setSource(bool pIsDyn)
87 {
88   if (pIsDyn)
89     m_BitField |= dynamic_flag;
90   else
91     m_BitField &= (~dynamic_flag);
92 }
93 
setInDyn()94 void ResolveInfo::setInDyn()
95 {
96   m_BitField |= indyn_flag;
97 }
98 
setType(uint32_t pType)99 void ResolveInfo::setType(uint32_t pType)
100 {
101   m_BitField &= ~TYPE_MASK;
102   m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK);
103 }
104 
setDesc(uint32_t pDesc)105 void ResolveInfo::setDesc(uint32_t pDesc)
106 {
107   m_BitField &= ~DESC_MASK;
108   m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK);
109 }
110 
setBinding(uint32_t pBinding)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 
setReserved(uint32_t pReserved)120 void ResolveInfo::setReserved(uint32_t pReserved)
121 {
122   m_BitField &= ~RESERVED_MASK;
123   m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK);
124 }
125 
setOther(uint32_t pOther)126 void ResolveInfo::setOther(uint32_t pOther)
127 {
128   setVisibility(static_cast<ResolveInfo::Visibility>(pOther & 0x3));
129 }
130 
setVisibility(ResolveInfo::Visibility pVisibility)131 void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility)
132 {
133   m_BitField &= ~VISIBILITY_MASK;
134   m_BitField |= pVisibility << VISIBILITY_OFFSET;
135 }
136 
setIsSymbol(bool pIsSymbol)137 void ResolveInfo::setIsSymbol(bool pIsSymbol)
138 {
139   if (pIsSymbol)
140     m_BitField |= symbol_flag;
141   else
142     m_BitField &= ~symbol_flag;
143 }
144 
isNull() const145 bool ResolveInfo::isNull() const
146 {
147   return (this == Null());
148 }
149 
isDyn() const150 bool ResolveInfo::isDyn() const
151 {
152   return (dynamic_flag == (m_BitField & DYN_MASK));
153 }
154 
isUndef() const155 bool ResolveInfo::isUndef() const
156 {
157   return (undefine_flag == (m_BitField & DESC_MASK));
158 }
159 
isDefine() const160 bool ResolveInfo::isDefine() const
161 {
162   return (define_flag == (m_BitField & DESC_MASK));
163 }
164 
isCommon() const165 bool ResolveInfo::isCommon() const
166 {
167   return (common_flag == (m_BitField & DESC_MASK));
168 }
169 
isIndirect() const170 bool ResolveInfo::isIndirect() const
171 {
172   return (indirect_flag == (m_BitField & DESC_MASK));
173 }
174 
175 // isGlobal - [L,W] == [0, 0]
isGlobal() const176 bool ResolveInfo::isGlobal() const
177 {
178   return (global_flag == (m_BitField & BINDING_MASK));
179 }
180 
181 // isWeak - [L,W] == [0, 1]
isWeak() const182 bool ResolveInfo::isWeak() const
183 {
184   return (weak_flag == (m_BitField & BINDING_MASK));
185 }
186 
187 // isLocal - [L,W] == [1, 0]
isLocal() const188 bool ResolveInfo::isLocal() const
189 {
190   return (local_flag == (m_BitField & BINDING_MASK));
191 }
192 
193 // isAbsolute - [L,W] == [1, 1]
isAbsolute() const194 bool ResolveInfo::isAbsolute() const
195 {
196   return (absolute_flag == (m_BitField & BINDING_MASK));
197 }
198 
isSymbol() const199 bool ResolveInfo::isSymbol() const
200 {
201   return (symbol_flag == (m_BitField & SYMBOL_MASK));
202 }
203 
isString() const204 bool ResolveInfo::isString() const
205 {
206   return (string_flag == (m_BitField & SYMBOL_MASK));
207 }
208 
isInDyn() const209 bool ResolveInfo::isInDyn() const
210 {
211   return (indyn_flag == (m_BitField & IN_DYN_MASK));
212 }
213 
type() const214 uint32_t ResolveInfo::type() const
215 {
216   return (m_BitField & TYPE_MASK) >> TYPE_OFFSET;
217 }
218 
desc() const219 uint32_t ResolveInfo::desc() const
220 {
221   return (m_BitField & DESC_MASK) >> DESC_OFFSET;
222 }
223 
binding() const224 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 
reserved() const235 uint32_t ResolveInfo::reserved() const
236 {
237   return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET;
238 }
239 
visibility() const240 ResolveInfo::Visibility ResolveInfo::visibility() const
241 {
242   return static_cast<ResolveInfo::Visibility>((m_BitField & VISIBILITY_MASK) >> VISIBILITY_OFFSET);
243 }
244 
compare(const ResolveInfo::key_type & pKey)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 
shouldForceLocal(const LinkerConfig & pConfig)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 //===----------------------------------------------------------------------===//
Create(const ResolveInfo::key_type & pKey)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 
Destroy(ResolveInfo * & pInfo)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 
Null()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