StaticResolver.cpp revision affc150dc44fab1911775a49636d0ce85333b634
18d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//===- StaticResolver.cpp -------------------------------------------------===// 28d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// 38d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// The MCLinker Project 48d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// 58d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// This file is distributed under the University of Illinois Open Source 68d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// License. See LICENSE.TXT for details. 78d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// 88d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//===----------------------------------------------------------------------===// 98d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include <mcld/LD/StaticResolver.h> 108d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include <mcld/LD/LDSymbol.h> 118d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include <mcld/Support/MsgHandling.h> 128d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 138d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guyusing namespace mcld; 148d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 158d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy//========================== 168d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// StaticResolver 178d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain GuyStaticResolver::~StaticResolver() 188d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy{ 198d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy} 208d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 216b50780363d3bb8db600c770183fa07677509ae8John Reckbool StaticResolver::resolve(ResolveInfo& __restrict__ pOld, 226b50780363d3bb8db600c770183fa07677509ae8John Reck const ResolveInfo& __restrict__ pNew, 236b50780363d3bb8db600c770183fa07677509ae8John Reck bool &pOverride) const 246b50780363d3bb8db600c770183fa07677509ae8John Reck{ 258d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 268d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* The state table itself. 278d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * The first index is a link_row and the second index is a bfd_link_hash_type. 288d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * 298d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * Cs -> all rest kind of common (d_C, wd_C) 308d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * Is -> all kind of indeirect 318d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy */ 328d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy static const enum LinkAction link_action[LAST_ORD][LAST_ORD] = 338d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy { 348d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* new\old U w_U d_U wd_U D w_D d_D wd_D C w_C, Cs, Is */ 358d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* U */ {NOACT, UND, UND, UND, NOACT, NOACT, DUND, DUND, NOACT, NOACT, NOACT, REFC }, 368d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* w_U */ {NOACT, NOACT, NOACT, WEAK, NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC }, 378d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* d_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 388d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* wd_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 398d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* D */ {DEF, DEF, DEF, DEF, MDEF, DEF, DEF, DEF, CDEF, CDEF, CDEF, MDEF }, 408d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* w_D */ {DEFW, DEFW, DEFW, DEFW, NOACT, NOACT, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT}, 418d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* d_D */ {MDEFD, MDEFD, DEFD, DEFD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF }, 428d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT}, 4348a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik /* C */ {COM, COM, COM, COM, CREF, COM, COM, COM, MBIG, COM, BIG, REFC }, 4448a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik /* w_C */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 4548a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik /* Cs */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, MBIG, MBIG, MBIG, REFC }, 468d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /* Is */ {IND, IND, IND, IND, MDEF, IND, IND, IND, CIND, CIND, CIND, MIND } 478d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy }; 488d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 498d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // Special cases: 508d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // * when a dynamic defined symbol meets a dynamic weak defined symbol, act 518d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // noting. 528d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // * when a undefined symbol meets a dynamic defined symbol, override by 538d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // dynamic defined first, then recover back to undefined symbol later. 548d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // * when a dynamic defined symbol meets a undefined symbol or a weak 558d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // undefined symbol, do not override, instead of marking. 568d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // * When a undefined symbol meets a dynamic defined symbol or a weak 578d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // undefined symbol meets a dynamic defined symbol, should override. 588d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // * When a common symbol meets a weak common symbol, adjust the size of 598d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // common symbol (ref: Google gold linker: resolve.cc) 608d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 618d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy unsigned int row = getOrdinate(pNew); 628d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy unsigned int col = getOrdinate(pOld); 638d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 648d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy bool cycle = false; 658d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy pOverride = false; 668d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy ResolveInfo* old = &pOld; 678d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy LinkAction action; 688d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy do { 698d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy cycle = false; 708d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy action = link_action[row][col]; 718d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 728d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy switch(action) { 738d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case FAIL: { /* abort. */ 748d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy fatal(diag::fail_sym_resolution) 758d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy << __FILE__ << __LINE__ 768d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy << "mclinker@googlegroups.com"; 778d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy return false; 788d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 798d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case NOACT: { /* no action. */ 808d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy pOverride = false; 818d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->overrideVisibility(pNew); 828d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 838d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 848d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case UND: /* override by symbol undefined symbol. */ 858d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case WEAK: /* override by symbol weak undefined. */ 868d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case DEF: /* override by symbol defined. */ 878d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case DEFW: /* override by symbol weak defined. */ 888d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case DEFD: /* override by symbol dynamic defined. */ 898d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case DEFWD: /* override by symbol dynamic weak defined. */ 908d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case COM: { /* override by symbol common defined. */ 91bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck pOverride = true; 92bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck old->override(pNew); 938d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 948d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 958d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case MDEFD: /* mark symbol dynamic defined. */ 968d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case MDEFWD: { /* mark symbol dynamic weak defined. */ 978d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy uint32_t binding = old->binding(); 98d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik old->override(pNew); 998d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->setBinding(binding); 1008d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy ignore(diag::mark_dynamic_defined) << old->name(); 101bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck pOverride = true; 1028d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 103bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck } 104bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck case DUND: 105bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck case DUNDW: { 1068d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->override(pNew); 1078d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->overrideVisibility(pNew); 1088d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->setDynamic(); 1098d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy pOverride = false; 1108d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 1118d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 1128d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case CREF: { /* Possibly warn about common reference to defined symbol. */ 1138d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // A common symbol does not override a definition. 1148d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy ignore(diag::comm_refer_to_define) << old->name(); 1158d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy pOverride = false; 1168d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 1178d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 1188d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case CDEF: { /* redefine existing common symbol. */ 1198d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // We've seen a common symbol and now we see a definition. The 1208d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // definition overrides. 1218d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // 1228d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // NOTE: m_Mesg uses 'name' instead of `name' for being compatible to GNU ld. 1238d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy ignore(diag::redefine_common) << old->name(); 1248d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->override(pNew); 1258d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy pOverride = true; 1268d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 1278d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 1288d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case BIG: { /* override by symbol common using largest size. */ 1298d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy if (old->size() < pNew.size()) 1308d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->setSize(pNew.size()); 131bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck old->overrideAttributes(pNew); 1328d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->overrideVisibility(pNew); 133bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck pOverride = true; 1348d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 1358d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 1368d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case MBIG: { /* mark common symbol by larger size. */ 1378d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy if (old->size() < pNew.size()) 138bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck old->setSize(pNew.size()); 1398d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy old->overrideVisibility(pNew); 1408d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy pOverride = false; 1418d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy break; 1428d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 1438d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy case CIND: { /* mark indirect symbol from existing common symbol. */ 1448d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy ignore(diag::indirect_refer_to_common) << old->name(); 1458d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 146e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung /* Fall through */ 147e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung case IND: { /* override by indirect symbol. */ 148e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung if (NULL == pNew.link()) { 149e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung fatal(diag::indirect_refer_to_inexist) << pNew.name(); 150e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung break; 1518d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy } 1528d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy 1538d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy /** Should detect the loop of indirect symbol during file reading **/ 1548d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // if (pNew.link()->isIndirect() && pNew.link()->link() == &pNew) { 1558d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // m_Mesg = "indirect symbol `"+pNew.name()+"' to `"+pNew.link()->name()+"' is a loop."; 1568d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy // 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 error(diag::multiple_definitions) << pNew.name(); 174 break; 175 } 176 case REFC: { /* Mark indirect symbol referenced and then CYCLE. */ 177 if (NULL == old->link()) { 178 fatal(diag::indirect_refer_to_inexist) << old->name(); 179 break; 180 } 181 182 old = old->link(); 183 col = getOrdinate(*old); 184 cycle = true; 185 break; 186 } 187 default: { 188 error(diag::undefined_situation) << action << old->name() << pNew.name(); 189 return false; 190 } 191 } // end of the big switch (action) 192 } while(cycle); 193 return true; 194} 195 196