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 13using namespace mcld; 14 15//========================== 16// StaticResolver 17StaticResolver::~StaticResolver() 18{ 19} 20 21bool 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