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