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