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