StaticResolver.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
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#include <cxxabi.h> 14 15using namespace mcld; 16 17//========================== 18// StaticResolver 19StaticResolver::~StaticResolver() 20{ 21} 22 23bool StaticResolver::resolve(ResolveInfo& __restrict__ pOld, 24 const ResolveInfo& __restrict__ pNew, 25 bool &pOverride, LDSymbol::ValueType pValue) const 26{ 27 28 /* The state table itself. 29 * The first index is a link_row and the second index is a bfd_link_hash_type. 30 * 31 * Cs -> all rest kind of common (d_C, wd_C) 32 * Is -> all kind of indirect 33 */ 34 static const enum LinkAction link_action[LAST_ORD][LAST_ORD] = 35 { 36 /* new\old U w_U d_U wd_U D w_D d_D wd_D C w_C, Cs, Is */ 37 /* U */ {NOACT, UND, UND, UND, NOACT, NOACT, DUND, DUND, NOACT, NOACT, NOACT, REFC }, 38 /* w_U */ {NOACT, NOACT, NOACT, WEAK, NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC }, 39 /* d_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 40 /* wd_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 41 /* D */ {DEF, DEF, DEF, DEF, MDEF, DEF, DEF, DEF, CDEF, CDEF, CDEF, MDEF }, 42 /* w_D */ {DEFW, DEFW, DEFW, DEFW, NOACT, NOACT, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT}, 43 /* d_D */ {MDEFD, MDEFD, DEFD, DEFD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF }, 44 /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT}, 45 /* C */ {COM, COM, COM, COM, CREF, COM, COM, COM, MBIG, COM, BIG, REFC }, 46 /* w_C */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 47 /* Cs */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, MBIG, MBIG, MBIG, REFC }, 48 /* Is */ {IND, IND, IND, IND, MDEF, IND, IND, IND, CIND, CIND, CIND, MIND } 49 }; 50 51 // Special cases: 52 // * when a dynamic defined symbol meets a dynamic weak defined symbol, act 53 // noting. 54 // * when a undefined symbol meets a dynamic defined symbol, override by 55 // dynamic defined first, then recover back to undefined symbol later. 56 // * when a dynamic defined symbol meets a undefined symbol or a weak 57 // undefined symbol, do not override, instead of marking. 58 // * When a undefined symbol meets a dynamic defined symbol or a weak 59 // undefined symbol meets a dynamic defined symbol, should override. 60 // * When a common symbol meets a weak common symbol, adjust the size of 61 // common symbol (ref: Google gold linker: resolve.cc) 62 63 unsigned int row = getOrdinate(pNew); 64 unsigned int col = getOrdinate(pOld); 65 66 bool cycle = false; 67 pOverride = false; 68 ResolveInfo* old = &pOld; 69 LinkAction action; 70 do { 71 cycle = false; 72 action = link_action[row][col]; 73 74 switch(action) { 75 case FAIL: { /* abort. */ 76 fatal(diag::fail_sym_resolution) 77 << __FILE__ << __LINE__ 78 << "mclinker@googlegroups.com"; 79 return false; 80 } 81 case NOACT: { /* no action. */ 82 pOverride = false; 83 old->overrideVisibility(pNew); 84 break; 85 } 86 case UND: /* override by symbol undefined symbol. */ 87 case WEAK: /* override by symbol weak undefined. */ 88 case DEF: /* override by symbol defined. */ 89 case DEFW: /* override by symbol weak defined. */ 90 case DEFD: /* override by symbol dynamic defined. */ 91 case DEFWD: /* override by symbol dynamic weak defined. */ 92 case COM: { /* override by symbol common defined. */ 93 pOverride = true; 94 old->override(pNew); 95 break; 96 } 97 case MDEFD: /* mark symbol dynamic defined. */ 98 case MDEFWD: { /* mark symbol dynamic weak defined. */ 99 uint32_t binding = old->binding(); 100 old->override(pNew); 101 old->setBinding(binding); 102 ignore(diag::mark_dynamic_defined) << old->name(); 103 pOverride = true; 104 break; 105 } 106 case DUND: 107 case DUNDW: { 108 old->overrideVisibility(pNew); 109 old->setDynamic(); 110 pOverride = false; 111 break; 112 } 113 case CREF: { /* Possibly warn about common reference to defined symbol. */ 114 // A common symbol does not override a definition. 115 ignore(diag::comm_refer_to_define) << old->name(); 116 pOverride = false; 117 break; 118 } 119 case CDEF: { /* redefine existing common symbol. */ 120 // We've seen a common symbol and now we see a definition. The 121 // definition overrides. 122 // 123 // NOTE: m_Mesg uses 'name' instead of `name' for being compatible to GNU ld. 124 ignore(diag::redefine_common) << old->name(); 125 old->override(pNew); 126 pOverride = true; 127 break; 128 } 129 case BIG: { /* override by symbol common using largest size. */ 130 if (old->size() < pNew.size()) 131 old->setSize(pNew.size()); 132 old->overrideAttributes(pNew); 133 old->overrideVisibility(pNew); 134 pOverride = true; 135 break; 136 } 137 case MBIG: { /* mark common symbol by larger size. */ 138 if (old->size() < pNew.size()) 139 old->setSize(pNew.size()); 140 old->overrideVisibility(pNew); 141 pOverride = false; 142 break; 143 } 144 case CIND: { /* mark indirect symbol from existing common symbol. */ 145 ignore(diag::indirect_refer_to_common) << old->name(); 146 } 147 /* Fall through */ 148 case IND: { /* override by indirect symbol. */ 149 if (NULL == pNew.link()) { 150 fatal(diag::indirect_refer_to_inexist) << pNew.name(); 151 break; 152 } 153 154 /** Should detect the loop of indirect symbol during file reading **/ 155 // if (pNew.link()->isIndirect() && pNew.link()->link() == &pNew) { 156 // m_Mesg = "indirect symbol `"+pNew.name()+"' to `"+pNew.link()->name()+"' is a loop."; 157 // return Resolver::Abort; 158 //} 159 160 // change the old symbol to the indirect symbol 161 old->setLink(pNew.link()); 162 pOverride = true; 163 break; 164 } 165 case MIND: { /* multiple indirect symbols. */ 166 // it is OK if they both point to the same symbol 167 if (old->link() == pNew.link()) { 168 pOverride = false; 169 break; 170 } 171 } 172 /* Fall through */ 173 case MDEF: { /* multiple definition error. */ 174 int status; 175 char* demangled_name = abi::__cxa_demangle(pNew.name(), NULL, NULL, 176 &status); 177 if (pOld.isDefine() && pNew.isDefine() && 178 pOld.isAbsolute() && pNew.isAbsolute() && 179 (pOld.desc() == pNew.desc() || pOld.desc() == ResolveInfo::NoType || 180 pNew.desc() == ResolveInfo::NoType)) { 181 if (pOld.outSymbol()->value() == pValue) { 182 pOverride = true; 183 old->override(pNew); 184 break; 185 } else { 186 if (demangled_name != NULL) { 187 error(diag::multiple_absolute_definitions) << demangled_name 188 << pOld.outSymbol()->value() << pValue; 189 } else { 190 error(diag::multiple_absolute_definitions) << pNew.name() 191 << pOld.outSymbol()->value() << pValue; 192 } 193 break; 194 } 195 } 196 if (demangled_name != NULL) { 197 error(diag::multiple_definitions) << demangled_name; 198 } else { 199 error(diag::multiple_definitions) << pNew.name(); 200 } 201 break; 202 } 203 case REFC: { /* Mark indirect symbol referenced and then CYCLE. */ 204 if (NULL == old->link()) { 205 fatal(diag::indirect_refer_to_inexist) << old->name(); 206 break; 207 } 208 209 old = old->link(); 210 col = getOrdinate(*old); 211 cycle = true; 212 break; 213 } 214 default: { 215 error(diag::undefined_situation) << action << old->name() << pNew.name(); 216 return false; 217 } 218 } // end of the big switch (action) 219 } while(cycle); 220 return true; 221} 222 223