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