Home | History | Annotate | Download | only in LD
      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
     19 StaticResolver::~StaticResolver() {
     20 }
     21 
     22 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 (at) 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