1 //===- StaticResolver.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/StaticResolver.h"
10
11 #include "mcld/LD/LDSymbol.h"
12 #include "mcld/Support/Demangle.h"
13 #include "mcld/Support/MsgHandling.h"
14
15 namespace mcld {
16
17 //==========================
18 // StaticResolver
~StaticResolver()19 StaticResolver::~StaticResolver() {
20 }
21
resolve(ResolveInfo & __restrict__ pOld,const ResolveInfo & __restrict__ pNew,bool & pOverride,LDSymbol::ValueType pValue) const22 bool StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
23 const ResolveInfo& __restrict__ pNew,
24 bool& pOverride,
25 LDSymbol::ValueType pValue) const {
26 /* The state table itself.
27 * The first index is a link_row and the second index is a bfd_link_hash_type.
28 *
29 * Cs -> all rest kind of common (d_C, wd_C)
30 * Is -> all kind of indirect
31 */
32 static const enum LinkAction link_action[LAST_ORD][LAST_ORD] = {
33 /* new\old U w_U d_U wd_U D w_D d_D wd_D C w_C, Cs, Is */ // NOLINT
34 /* U */ {NOACT, UND, UND, UND, NOACT, NOACT, DUND, DUND, NOACT, NOACT, NOACT, REFC }, // NOLINT
35 /* w_U */ {NOACT, NOACT, NOACT, WEAK, NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC }, // NOLINT
36 /* d_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, // NOLINT
37 /* wd_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, // NOLINT
38 /* D */ {DEF, DEF, DEF, DEF, MDEF, DEF, DEF, DEF, CDEF, CDEF, CDEF, MDEF }, // NOLINT
39 /* w_D */ {DEFW, DEFW, DEFW, DEFW, NOACT, NOACT, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT}, // NOLINT
40 /* d_D */ {MDEFD, MDEFD, DEFD, DEFD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF }, // NOLINT
41 /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT}, // NOLINT
42 /* C */ {COM, COM, COM, COM, CREF, COM, COM, COM, MBIG, COM, BIG, REFC }, // NOLINT
43 /* w_C */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, // NOLINT
44 /* Cs */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, MBIG, MBIG, MBIG, REFC }, // NOLINT
45 /* Is */ {IND, IND, IND, IND, MDEF, IND, IND, IND, CIND, CIND, CIND, MIND } // NOLINT
46 };
47
48 // Special cases:
49 // * when a dynamic defined symbol meets a dynamic weak defined symbol, act
50 // noting.
51 // * when a undefined symbol meets a dynamic defined symbol, override by
52 // dynamic defined first, then recover back to undefined symbol later.
53 // * when a dynamic defined symbol meets a undefined symbol or a weak
54 // undefined symbol, do not override, instead of marking.
55 // * When a undefined symbol meets a dynamic defined symbol or a weak
56 // undefined symbol meets a dynamic defined symbol, should override.
57 // * When a common symbol meets a weak common symbol, adjust the size of
58 // common symbol.
59
60 unsigned int row = getOrdinate(pNew);
61 unsigned int col = getOrdinate(pOld);
62
63 bool cycle = false;
64 pOverride = false;
65 ResolveInfo* old = &pOld;
66 LinkAction action;
67 do {
68 cycle = false;
69 action = link_action[row][col];
70
71 switch (action) {
72 case FAIL: { /* abort. */
73 fatal(diag::fail_sym_resolution) << __FILE__ << __LINE__
74 << "mclinker@googlegroups.com";
75 return false;
76 }
77 case NOACT: { /* no action. */
78 pOverride = false;
79 old->overrideVisibility(pNew);
80 break;
81 }
82 case UND: /* override by symbol undefined symbol. */
83 case WEAK: /* override by symbol weak undefined. */
84 case DEF: /* override by symbol defined. */
85 case DEFW: /* override by symbol weak defined. */
86 case DEFD: /* override by symbol dynamic defined. */
87 case DEFWD: /* override by symbol dynamic weak defined. */
88 case COM: { /* override by symbol common defined. */
89 pOverride = true;
90 old->override(pNew);
91 break;
92 }
93 case MDEFD: /* mark symbol dynamic defined. */
94 case MDEFWD: { /* mark symbol dynamic weak defined. */
95 uint32_t binding = old->binding();
96 old->override(pNew);
97 old->setBinding(binding);
98 ignore(diag::mark_dynamic_defined) << old->name();
99 pOverride = true;
100 break;
101 }
102 case DUND:
103 case DUNDW: {
104 old->overrideVisibility(pNew);
105 old->setDynamic();
106 pOverride = false;
107 break;
108 }
109 case CREF: { /* Possibly warn about common reference to defined symbol. */
110 // A common symbol does not override a definition.
111 ignore(diag::comm_refer_to_define) << old->name();
112 pOverride = false;
113 break;
114 }
115 case CDEF: { /* redefine existing common symbol. */
116 // We've seen a common symbol and now we see a definition. The
117 // definition overrides.
118 //
119 // NOTE: m_Mesg uses 'name' instead of `name' for being compatible to
120 // GNU ld.
121 ignore(diag::redefine_common) << old->name();
122 old->override(pNew);
123 pOverride = true;
124 break;
125 }
126 case BIG: { /* override by symbol common using largest size. */
127 if (old->size() < pNew.size())
128 old->setSize(pNew.size());
129 old->overrideAttributes(pNew);
130 old->overrideVisibility(pNew);
131 pOverride = true;
132 break;
133 }
134 case MBIG: { /* mark common symbol by larger size. */
135 if (old->size() < pNew.size())
136 old->setSize(pNew.size());
137 old->overrideVisibility(pNew);
138 pOverride = false;
139 break;
140 }
141 case CIND: { /* mark indirect symbol from existing common symbol. */
142 ignore(diag::indirect_refer_to_common) << old->name();
143 }
144 /* Fall through */
145 case IND: { /* override by indirect symbol. */
146 if (pNew.link() == NULL) {
147 fatal(diag::indirect_refer_to_inexist) << pNew.name();
148 break;
149 }
150
151 /** Should detect the loop of indirect symbol during file reading **/
152 // if (pNew.link()->isIndirect() && pNew.link()->link() == &pNew) {
153 // m_Mesg = "indirect symbol `"+pNew.name()+"' to
154 // `"+pNew.link()->name()+"' is a loop.";
155 // return Resolver::Abort;
156 //}
157
158 // change the old symbol to the indirect symbol
159 old->setLink(pNew.link());
160 pOverride = true;
161 break;
162 }
163 case MIND: { /* multiple indirect symbols. */
164 // it is OK if they both point to the same symbol
165 if (old->link() == pNew.link()) {
166 pOverride = false;
167 break;
168 }
169 }
170 /* Fall through */
171 case MDEF: { /* multiple definition error. */
172 if (pOld.isDefine() && pNew.isDefine() && pOld.isAbsolute() &&
173 pNew.isAbsolute() &&
174 (pOld.desc() == pNew.desc() || pOld.desc() == ResolveInfo::NoType ||
175 pNew.desc() == ResolveInfo::NoType)) {
176 if (pOld.outSymbol()->value() == pValue) {
177 pOverride = true;
178 old->override(pNew);
179 break;
180 } else {
181 error(diag::multiple_absolute_definitions)
182 << demangleName(pNew.name()) << pOld.outSymbol()->value()
183 << pValue;
184 break;
185 }
186 }
187
188 error(diag::multiple_definitions) << demangleName(pNew.name());
189 break;
190 }
191 case REFC: { /* Mark indirect symbol referenced and then CYCLE. */
192 if (old->link() == NULL) {
193 fatal(diag::indirect_refer_to_inexist) << old->name();
194 break;
195 }
196
197 old = old->link();
198 col = getOrdinate(*old);
199 cycle = true;
200 break;
201 }
202 default: {
203 error(diag::undefined_situation) << action << old->name()
204 << pNew.name();
205 return false;
206 }
207 } // end of the big switch (action)
208 } while (cycle);
209 return true;
210 }
211
212 } // namespace mcld
213