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
17using namespace mcld;
18
19/// g_NullResolveInfo - a pointer to Null ResolveInfo.
20static ResolveInfo* g_NullResolveInfo = NULL;
21
22//===----------------------------------------------------------------------===//
23// ResolveInfo
24//===----------------------------------------------------------------------===//
25ResolveInfo::ResolveInfo()
26  : m_Size(0), m_BitField(0) {
27  m_Ptr.sym_ptr = 0;
28}
29
30ResolveInfo::~ResolveInfo()
31{
32}
33
34void ResolveInfo::override(const ResolveInfo& pFrom)
35{
36  m_Size = pFrom.m_Size;
37  overrideAttributes(pFrom);
38  overrideVisibility(pFrom);
39}
40
41void 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
49void 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
76void ResolveInfo::setRegular()
77{
78  m_BitField &= (~dynamic_flag);
79}
80
81void ResolveInfo::setDynamic()
82{
83  m_BitField |= dynamic_flag;
84}
85
86void ResolveInfo::setSource(bool pIsDyn)
87{
88  if (pIsDyn)
89    m_BitField |= dynamic_flag;
90  else
91    m_BitField &= (~dynamic_flag);
92}
93
94void ResolveInfo::setInDyn()
95{
96  m_BitField |= indyn_flag;
97}
98
99void ResolveInfo::setType(uint32_t pType)
100{
101  m_BitField &= ~TYPE_MASK;
102  m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK);
103}
104
105void ResolveInfo::setDesc(uint32_t pDesc)
106{
107  m_BitField &= ~DESC_MASK;
108  m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK);
109}
110
111void 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
120void ResolveInfo::setReserved(uint32_t pReserved)
121{
122  m_BitField &= ~RESERVED_MASK;
123  m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK);
124}
125
126void ResolveInfo::setOther(uint32_t pOther)
127{
128  setVisibility(static_cast<ResolveInfo::Visibility>(pOther & 0x3));
129}
130
131void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility)
132{
133  m_BitField &= ~VISIBILITY_MASK;
134  m_BitField |= pVisibility << VISIBILITY_OFFSET;
135}
136
137void ResolveInfo::setIsSymbol(bool pIsSymbol)
138{
139  if (pIsSymbol)
140    m_BitField |= symbol_flag;
141  else
142    m_BitField &= ~symbol_flag;
143}
144
145bool ResolveInfo::isNull() const
146{
147  return (this == Null());
148}
149
150bool ResolveInfo::isDyn() const
151{
152  return (dynamic_flag == (m_BitField & DYN_MASK));
153}
154
155bool ResolveInfo::isUndef() const
156{
157  return (undefine_flag == (m_BitField & DESC_MASK));
158}
159
160bool ResolveInfo::isDefine() const
161{
162  return (define_flag == (m_BitField & DESC_MASK));
163}
164
165bool ResolveInfo::isCommon() const
166{
167  return (common_flag == (m_BitField & DESC_MASK));
168}
169
170bool ResolveInfo::isIndirect() const
171{
172  return (indirect_flag == (m_BitField & DESC_MASK));
173}
174
175// isGlobal - [L,W] == [0, 0]
176bool ResolveInfo::isGlobal() const
177{
178  return (global_flag == (m_BitField & BINDING_MASK));
179}
180
181// isWeak - [L,W] == [0, 1]
182bool ResolveInfo::isWeak() const
183{
184  return (weak_flag == (m_BitField & BINDING_MASK));
185}
186
187// isLocal - [L,W] == [1, 0]
188bool ResolveInfo::isLocal() const
189{
190  return (local_flag == (m_BitField & BINDING_MASK));
191}
192
193// isAbsolute - [L,W] == [1, 1]
194bool ResolveInfo::isAbsolute() const
195{
196  return (absolute_flag == (m_BitField & BINDING_MASK));
197}
198
199bool ResolveInfo::isSymbol() const
200{
201  return (symbol_flag == (m_BitField & SYMBOL_MASK));
202}
203
204bool ResolveInfo::isString() const
205{
206  return (string_flag == (m_BitField & SYMBOL_MASK));
207}
208
209bool ResolveInfo::isInDyn() const
210{
211  return (indyn_flag == (m_BitField & IN_DYN_MASK));
212}
213
214uint32_t ResolveInfo::type() const
215{
216  return (m_BitField & TYPE_MASK) >> TYPE_OFFSET;
217}
218
219uint32_t ResolveInfo::desc() const
220{
221  return (m_BitField & DESC_MASK) >> DESC_OFFSET;
222}
223
224uint32_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
235uint32_t ResolveInfo::reserved() const
236{
237  return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET;
238}
239
240ResolveInfo::Visibility ResolveInfo::visibility() const
241{
242  return static_cast<ResolveInfo::Visibility>((m_BitField & VISIBILITY_MASK) >> VISIBILITY_OFFSET);
243}
244
245bool 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
253bool 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//===----------------------------------------------------------------------===//
271ResolveInfo* 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
286void 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
299ResolveInfo* 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