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 18 StaticResolver::~StaticResolver() 19 { 20 } 21 22 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 (at) 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