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