StaticResolver.cpp revision affc150dc44fab1911775a49636d0ce85333b634
18d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//===- StaticResolver.cpp -------------------------------------------------===//
28d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//
38d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//                     The MCLinker Project
48d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//
58d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// This file is distributed under the University of Illinois Open Source
68d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// License. See LICENSE.TXT for details.
78d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//
88d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//===----------------------------------------------------------------------===//
98d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include <mcld/LD/StaticResolver.h>
108d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include <mcld/LD/LDSymbol.h>
118d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include <mcld/Support/MsgHandling.h>
128d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
138d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guyusing namespace mcld;
148d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
158d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//==========================
168d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// StaticResolver
178d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain GuyStaticResolver::~StaticResolver()
188d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy{
198d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
208d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
216b50780363d3bb8db600c770183fa07677509ae8John Reckbool StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
226b50780363d3bb8db600c770183fa07677509ae8John Reck                             const ResolveInfo& __restrict__ pNew,
236b50780363d3bb8db600c770183fa07677509ae8John Reck                             bool &pOverride) const
246b50780363d3bb8db600c770183fa07677509ae8John Reck{
258d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
268d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  /* The state table itself.
278d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy   * The first index is a link_row and the second index is a bfd_link_hash_type.
288d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy   *
298d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy   * Cs -> all rest kind of common (d_C, wd_C)
308d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy   * Is -> all kind of indeirect
318d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy   */
328d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  static const enum LinkAction link_action[LAST_ORD][LAST_ORD] =
338d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  {
348d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* new\old  U       w_U     d_U    wd_U   D      w_D    d_D    wd_D   C      w_C,   Cs,    Is   */
358d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* U    */ {NOACT,  UND,    UND,   UND,   NOACT, NOACT, DUND,  DUND,  NOACT, NOACT, NOACT, REFC },
368d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* w_U  */ {NOACT,  NOACT,  NOACT, WEAK,  NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC },
378d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* d_U  */ {NOACT,  NOACT,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
388d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* wd_U */ {NOACT,  NOACT,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
398d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* D    */ {DEF,    DEF,    DEF,   DEF,   MDEF,  DEF,   DEF,   DEF,   CDEF,  CDEF,  CDEF,  MDEF },
408d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* w_D  */ {DEFW,   DEFW,   DEFW,  DEFW,  NOACT, NOACT, DEFW,  DEFW,  NOACT, NOACT, NOACT, NOACT},
418d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* d_D  */ {MDEFD,  MDEFD,  DEFD,  DEFD,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF },
428d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT},
4348a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik    /* C    */ {COM,    COM,    COM,   COM,   CREF,  COM,   COM,   COM,   MBIG,  COM,   BIG,   REFC },
4448a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik    /* w_C  */ {COM,    COM,    COM,   COM,   NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
4548a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik    /* Cs   */ {COM,    COM,    COM,   COM,   NOACT, NOACT, NOACT, NOACT, MBIG,  MBIG,  MBIG,  REFC },
468d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    /* Is   */ {IND,    IND,    IND,   IND,   MDEF,  IND,   IND,   IND,   CIND,  CIND,  CIND,  MIND }
478d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  };
488d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
498d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  // Special cases:
508d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  // * when a dynamic defined symbol meets a dynamic weak defined symbol, act
518d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  //   noting.
528d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  // * when a undefined symbol meets a dynamic defined symbol, override by
538d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  //   dynamic defined first, then recover back to undefined symbol later.
548d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  // * when a dynamic defined symbol meets a undefined symbol or a weak
558d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  //   undefined symbol, do not override, instead of marking.
568d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  // * When a undefined symbol meets a dynamic defined symbol or a weak
578d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  //   undefined symbol meets a dynamic defined symbol, should override.
588d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  // * When a common symbol meets a weak common symbol, adjust the size of
598d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  //   common symbol (ref: Google gold linker: resolve.cc)
608d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
618d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  unsigned int row = getOrdinate(pNew);
628d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  unsigned int col = getOrdinate(pOld);
638d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
648d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  bool cycle = false;
658d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  pOverride = false;
668d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  ResolveInfo* old = &pOld;
678d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  LinkAction action;
688d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy  do {
698d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    cycle = false;
708d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    action = link_action[row][col];
718d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
728d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    switch(action) {
738d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case FAIL: {       /* abort.  */
748d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        fatal(diag::fail_sym_resolution)
758d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy                << __FILE__ << __LINE__
768d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy                << "mclinker@googlegroups.com";
778d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        return false;
788d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
798d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case NOACT: {      /* no action.  */
808d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        pOverride = false;
818d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->overrideVisibility(pNew);
828d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
838d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
848d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case UND:          /* override by symbol undefined symbol.  */
858d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case WEAK:         /* override by symbol weak undefined.  */
868d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case DEF:          /* override by symbol defined.  */
878d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case DEFW:         /* override by symbol weak defined.  */
888d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case DEFD:         /* override by symbol dynamic defined.  */
898d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case DEFWD:        /* override by symbol dynamic weak defined. */
908d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case COM: {        /* override by symbol common defined.  */
91bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        pOverride = true;
92bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        old->override(pNew);
938d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
948d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
958d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case MDEFD:        /* mark symbol dynamic defined.  */
968d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case MDEFWD: {     /* mark symbol dynamic weak defined.  */
978d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        uint32_t binding = old->binding();
98d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        old->override(pNew);
998d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->setBinding(binding);
1008d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        ignore(diag::mark_dynamic_defined) << old->name();
101bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        pOverride = true;
1028d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
103bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck      }
104bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck      case DUND:
105bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck      case DUNDW: {
1068d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->override(pNew);
1078d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->overrideVisibility(pNew);
1088d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->setDynamic();
1098d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        pOverride = false;
1108d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
1118d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
1128d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case CREF: {       /* Possibly warn about common reference to defined symbol.  */
1138d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        // A common symbol does not override a definition.
1148d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        ignore(diag::comm_refer_to_define) << old->name();
1158d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        pOverride = false;
1168d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
1178d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
1188d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case CDEF: {       /* redefine existing common symbol.  */
1198d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        // We've seen a common symbol and now we see a definition.  The
1208d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        // definition overrides.
1218d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        //
1228d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy	// NOTE: m_Mesg uses 'name' instead of `name' for being compatible to GNU ld.
1238d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        ignore(diag::redefine_common) << old->name();
1248d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->override(pNew);
1258d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        pOverride = true;
1268d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
1278d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
1288d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case BIG: {        /* override by symbol common using largest size.  */
1298d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        if (old->size() < pNew.size())
1308d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy          old->setSize(pNew.size());
131bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        old->overrideAttributes(pNew);
1328d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->overrideVisibility(pNew);
133bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        pOverride = true;
1348d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
1358d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
1368d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case MBIG: {       /* mark common symbol by larger size. */
1378d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        if (old->size() < pNew.size())
138bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck          old->setSize(pNew.size());
1398d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        old->overrideVisibility(pNew);
1408d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        pOverride = false;
1418d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        break;
1428d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
1438d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      case CIND: {       /* mark indirect symbol from existing common symbol.  */
1448d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy         ignore(diag::indirect_refer_to_common) << old->name();
1458d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy      }
146e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung      /* Fall through */
147e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung      case IND: {        /* override by indirect symbol.  */
148e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung        if (NULL == pNew.link()) {
149e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung          fatal(diag::indirect_refer_to_inexist) << pNew.name();
150e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung          break;
1518d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        }
1528d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1538d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        /** Should detect the loop of indirect symbol during file reading **/
1548d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        // if (pNew.link()->isIndirect() && pNew.link()->link() == &pNew) {
1558d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        //  m_Mesg = "indirect symbol `"+pNew.name()+"' to `"+pNew.link()->name()+"' is a loop.";
1568d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        //  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        error(diag::multiple_definitions) << pNew.name();
174        break;
175      }
176      case REFC: {       /* Mark indirect symbol referenced and then CYCLE.  */
177        if (NULL == old->link()) {
178          fatal(diag::indirect_refer_to_inexist) << old->name();
179          break;
180        }
181
182        old = old->link();
183        col = getOrdinate(*old);
184        cycle = true;
185        break;
186      }
187      default: {
188        error(diag::undefined_situation) << action << old->name() << pNew.name();
189        return false;
190      }
191    } // end of the big switch (action)
192  } while(cycle);
193  return true;
194}
195
196