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