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