• 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/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