1//===- ResolveInfo.h ------------------------------------------------------===//
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#ifndef MCLD_LD_RESOLVEINFO_H_
10#define MCLD_LD_RESOLVEINFO_H_
11
12#include <llvm/ADT/StringRef.h>
13#include <llvm/Support/DataTypes.h>
14
15namespace mcld {
16
17class LDSymbol;
18class LinkerConfig;
19
20/** \class ResolveInfo
21 *  \brief ResolveInfo records the information about how to resolve a symbol.
22 *
23 *  A symbol must have some `attributes':
24 *  - Desc - Defined, Reference, Common or Indirect
25 *  - Binding - Global, Local, Weak
26 *  - IsDyn - appear in dynamic objects or regular objects
27 *  - Type - what the symbol refers to
28 *  - Size  - the size of the symbol point to
29 *  - Value - the pointer to another LDSymbol
30 *  In order to save the memory and speed up the performance, FragmentLinker
31 *uses
32 *  a bit field to store all attributes.
33 *
34 *  The maximum string length is (2^16 - 1)
35 */
36class ResolveInfo {
37  friend class FragmentLinker;
38  friend class IRBuilder;
39
40 public:
41  typedef uint64_t SizeType;
42
43  /** \enum Type
44   *  \brief What the symbol stand for
45   *
46   *  It is like ELF32_ST_TYPE
47   *  MachO does not need this, and can not jump between Thumb and ARM code.
48   */
49  enum Type {
50    NoType = 0,
51    Object = 1,
52    Function = 2,
53    Section = 3,
54    File = 4,
55    CommonBlock = 5,
56    ThreadLocal = 6,
57    IndirectFunc = 10,
58    LoProc = 13,
59    HiProc = 15
60  };
61
62  /** \enum Desc
63   *  \brief Description of the symbols.
64   *
65   *   Follow the naming in MachO. Like MachO nlist::n_desc
66   *   In ELF, is a part of st_shndx
67   */
68  enum Desc { Undefined = 0, Define = 1, Common = 2, Indirect = 3, NoneDesc };
69
70  enum Binding { Global = 0, Weak = 1, Local = 2, Absolute = 3, NoneBinding };
71
72  enum Visibility { Default = 0, Internal = 1, Hidden = 2, Protected = 3 };
73
74  // -----  For HashTable  ----- //
75  typedef llvm::StringRef key_type;
76
77 public:
78  // -----  factory method  ----- //
79  static ResolveInfo* Create(const key_type& pKey);
80
81  static void Destroy(ResolveInfo*& pInfo);
82
83  static ResolveInfo* Null();
84
85  // -----  modifiers  ----- //
86  /// setRegular - set the source of the file is a regular object
87  void setRegular();
88
89  /// setDynamic - set the source of the file is a dynamic object
90  void setDynamic();
91
92  /// setSource - set the source of the file
93  /// @param pIsDyn is the source from a dynamic object?
94  void setSource(bool pIsDyn);
95
96  void setType(uint32_t pType);
97
98  void setDesc(uint32_t pDesc);
99
100  void setBinding(uint32_t pBinding);
101
102  void setOther(uint32_t pOther);
103
104  void setVisibility(Visibility pVisibility);
105
106  void setIsSymbol(bool pIsSymbol);
107
108  void setReserved(uint32_t pReserved);
109
110  void setSize(SizeType pSize) { m_Size = pSize; }
111
112  void override(const ResolveInfo& pForm);
113
114  void overrideAttributes(const ResolveInfo& pFrom);
115
116  void overrideVisibility(const ResolveInfo& pFrom);
117
118  void setSymPtr(const LDSymbol* pSymPtr) {
119    m_Ptr.sym_ptr = const_cast<LDSymbol*>(pSymPtr);
120  }
121
122  void setLink(const ResolveInfo* pTarget) {
123    m_Ptr.info_ptr = const_cast<ResolveInfo*>(pTarget);
124    m_BitField |= indirect_flag;
125  }
126
127  /// setInDyn - set if the symbol has been seen in the dynamic objects. Once
128  /// InDyn set, then it won't be set back to false
129  void setInDyn();
130
131  // -----  observers  ----- //
132  bool isNull() const;
133
134  bool isSymbol() const;
135
136  bool isString() const;
137
138  bool isGlobal() const;
139
140  bool isWeak() const;
141
142  bool isLocal() const;
143
144  bool isAbsolute() const;
145
146  bool isDefine() const;
147
148  bool isUndef() const;
149
150  bool isDyn() const;
151
152  bool isCommon() const;
153
154  bool isIndirect() const;
155
156  bool isInDyn() const;
157
158  uint32_t type() const;
159
160  uint32_t desc() const;
161
162  uint32_t binding() const;
163
164  uint32_t reserved() const;
165
166  uint8_t other() const { return (uint8_t)visibility(); }
167
168  Visibility visibility() const;
169
170  LDSymbol* outSymbol() { return m_Ptr.sym_ptr; }
171
172  const LDSymbol* outSymbol() const { return m_Ptr.sym_ptr; }
173
174  ResolveInfo* link() { return m_Ptr.info_ptr; }
175
176  const ResolveInfo* link() const { return m_Ptr.info_ptr; }
177
178  SizeType size() const { return m_Size; }
179
180  const char* name() const { return m_Name; }
181
182  unsigned int nameSize() const { return (m_BitField >> NAME_LENGTH_OFFSET); }
183
184  uint32_t info() const { return (m_BitField & INFO_MASK); }
185
186  uint32_t bitfield() const { return m_BitField; }
187
188  // shouldForceLocal - check if this symbol should be forced to local
189  bool shouldForceLocal(const LinkerConfig& pConfig);
190
191  // -----  For HashTable  ----- //
192  bool compare(const key_type& pKey);
193
194 private:
195  static const uint32_t GLOBAL_OFFSET = 0;
196  static const uint32_t GLOBAL_MASK = 1;
197
198  static const uint32_t DYN_OFFSET = 1;
199  static const uint32_t DYN_MASK = 1 << DYN_OFFSET;
200
201  static const uint32_t DESC_OFFSET = 2;
202  static const uint32_t DESC_MASK = 0x3 << DESC_OFFSET;
203
204  static const uint32_t LOCAL_OFFSET = 4;
205  static const uint32_t LOCAL_MASK = 1 << LOCAL_OFFSET;
206
207  static const uint32_t BINDING_MASK = GLOBAL_MASK | LOCAL_MASK;
208
209  static const uint32_t VISIBILITY_OFFSET = 5;
210  static const uint32_t VISIBILITY_MASK = 0x3 << VISIBILITY_OFFSET;
211
212  static const uint32_t TYPE_OFFSET = 7;
213  static const uint32_t TYPE_MASK = 0xF << TYPE_OFFSET;
214
215  static const uint32_t SYMBOL_OFFSET = 11;
216  static const uint32_t SYMBOL_MASK = 1 << SYMBOL_OFFSET;
217
218  static const uint32_t RESERVED_OFFSET = 12;
219  static const uint32_t RESERVED_MASK = 0xF << RESERVED_OFFSET;
220
221  static const uint32_t IN_DYN_OFFSET = 16;
222  static const uint32_t IN_DYN_MASK = 1 << IN_DYN_OFFSET;
223
224  static const uint32_t NAME_LENGTH_OFFSET = 17;
225  static const uint32_t INFO_MASK = 0xF;
226  static const uint32_t RESOLVE_MASK = 0xFFFF;
227
228  union SymOrInfo {
229    LDSymbol* sym_ptr;
230    ResolveInfo* info_ptr;
231  };
232
233 public:
234  static const uint32_t global_flag = 0 << GLOBAL_OFFSET;
235  static const uint32_t weak_flag = 1 << GLOBAL_OFFSET;
236  static const uint32_t regular_flag = 0 << DYN_OFFSET;
237  static const uint32_t dynamic_flag = 1 << DYN_OFFSET;
238  static const uint32_t undefine_flag = 0 << DESC_OFFSET;
239  static const uint32_t define_flag = 1 << DESC_OFFSET;
240  static const uint32_t common_flag = 2 << DESC_OFFSET;
241  static const uint32_t indirect_flag = 3 << DESC_OFFSET;
242  static const uint32_t local_flag = 1 << LOCAL_OFFSET;
243  static const uint32_t absolute_flag = BINDING_MASK;
244  static const uint32_t object_flag = Object << TYPE_OFFSET;
245  static const uint32_t function_flag = Function << TYPE_OFFSET;
246  static const uint32_t section_flag = Section << TYPE_OFFSET;
247  static const uint32_t file_flag = File << TYPE_OFFSET;
248  static const uint32_t string_flag = 0 << SYMBOL_OFFSET;
249  static const uint32_t symbol_flag = 1 << SYMBOL_OFFSET;
250  static const uint32_t indyn_flag = 1 << IN_DYN_OFFSET;
251
252 private:
253  ResolveInfo();
254  ResolveInfo(const ResolveInfo& pCopy);
255  ResolveInfo& operator=(const ResolveInfo& pCopy);
256  ~ResolveInfo();
257
258 private:
259  SizeType m_Size;
260  SymOrInfo m_Ptr;
261
262  /** m_BitField
263   *  31     ...    17 16    15    12 11     10..7 6      ..    5 4     3   2
264   * 1   0
265   * |length of m_Name|InDyn|reserved|Symbol|Type |ELF
266   * visibility|Local|Com|Def|Dyn|Weak|
267   */
268  uint32_t m_BitField;
269  char m_Name[];
270};
271
272}  // namespace mcld
273
274#endif  // MCLD_LD_RESOLVEINFO_H_
275