StaticResolver.cpp revision affc150dc44fab1911775a49636d0ce85333b634
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- StaticResolver.cpp -------------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/StaticResolver.h> 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/LDSymbol.h> 11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//========================== 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// StaticResolver 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStaticResolver::~StaticResolver() 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 21affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool StaticResolver::resolve(ResolveInfo& __restrict__ pOld, 22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const ResolveInfo& __restrict__ pNew, 23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool &pOverride) const 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* The state table itself. 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * The first index is a link_row and the second index is a bfd_link_hash_type. 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Cs -> all rest kind of common (d_C, wd_C) 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Is -> all kind of indeirect 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao static const enum LinkAction link_action[LAST_ORD][LAST_ORD] = 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* new\old U w_U d_U wd_U D w_D d_D wd_D C w_C, Cs, Is */ 35affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* U */ {NOACT, UND, UND, UND, NOACT, NOACT, DUND, DUND, NOACT, NOACT, NOACT, REFC }, 36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* w_U */ {NOACT, NOACT, NOACT, WEAK, NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC }, 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* d_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* wd_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* D */ {DEF, DEF, DEF, DEF, MDEF, DEF, DEF, DEF, CDEF, CDEF, CDEF, MDEF }, 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* w_D */ {DEFW, DEFW, DEFW, DEFW, NOACT, NOACT, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT}, 41affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* d_D */ {MDEFD, MDEFD, DEFD, DEFD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF }, 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT}, 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* C */ {COM, COM, COM, COM, CREF, COM, COM, COM, MBIG, COM, BIG, REFC }, 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* w_C */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* Cs */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, MBIG, MBIG, MBIG, REFC }, 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* Is */ {IND, IND, IND, IND, MDEF, IND, IND, IND, CIND, CIND, CIND, MIND } 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao }; 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Special cases: 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * when a dynamic defined symbol meets a dynamic weak defined symbol, act 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // noting. 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * when a undefined symbol meets a dynamic defined symbol, override by 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // dynamic defined first, then recover back to undefined symbol later. 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * when a dynamic defined symbol meets a undefined symbol or a weak 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // undefined symbol, do not override, instead of marking. 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * When a undefined symbol meets a dynamic defined symbol or a weak 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // undefined symbol meets a dynamic defined symbol, should override. 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * When a common symbol meets a weak common symbol, adjust the size of 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // common symbol (ref: Google gold linker: resolve.cc) 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int row = getOrdinate(pNew); 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int col = getOrdinate(pOld); 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool cycle = false; 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* old = &pOld; 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao LinkAction action; 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao do { 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao cycle = false; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao action = link_action[row][col]; 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(action) { 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case FAIL: { /* abort. */ 74affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::fail_sym_resolution) 75affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << __FILE__ << __LINE__ 76affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << "mclinker@googlegroups.com"; 77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return false; 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case NOACT: { /* no action. */ 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case UND: /* override by symbol undefined symbol. */ 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case WEAK: /* override by symbol weak undefined. */ 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DEF: /* override by symbol defined. */ 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DEFW: /* override by symbol weak defined. */ 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DEFD: /* override by symbol dynamic defined. */ 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DEFWD: /* override by symbol dynamic weak defined. */ 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case COM: { /* override by symbol common defined. */ 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->override(pNew); 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case MDEFD: /* mark symbol dynamic defined. */ 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case MDEFWD: { /* mark symbol dynamic weak defined. */ 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t binding = old->binding(); 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->override(pNew); 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setBinding(binding); 100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::mark_dynamic_defined) << old->name(); 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DUND: 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DUNDW: { 106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang old->override(pNew); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang old->setDynamic(); 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case CREF: { /* Possibly warn about common reference to defined symbol. */ 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // A common symbol does not override a definition. 114affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::comm_refer_to_define) << old->name(); 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case CDEF: { /* redefine existing common symbol. */ 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // We've seen a common symbol and now we see a definition. The 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // definition overrides. 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // NOTE: m_Mesg uses 'name' instead of `name' for being compatible to GNU ld. 123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::redefine_common) << old->name(); 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->override(pNew); 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case BIG: { /* override by symbol common using largest size. */ 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (old->size() < pNew.size()) 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setSize(pNew.size()); 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideAttributes(pNew); 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case MBIG: { /* mark common symbol by larger size. */ 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (old->size() < pNew.size()) 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setSize(pNew.size()); 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case CIND: { /* mark indirect symbol from existing common symbol. */ 144affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::indirect_refer_to_common) << old->name(); 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* Fall through */ 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case IND: { /* override by indirect symbol. */ 148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (NULL == pNew.link()) { 149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::indirect_refer_to_inexist) << pNew.name(); 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /** Should detect the loop of indirect symbol during file reading **/ 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if (pNew.link()->isIndirect() && pNew.link()->link() == &pNew) { 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // m_Mesg = "indirect symbol `"+pNew.name()+"' to `"+pNew.link()->name()+"' is a loop."; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // return Resolver::Abort; 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao //} 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // change the old symbol to the indirect symbol 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setLink(pNew.link()); 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case MIND: { /* multiple indirect symbols. */ 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // it is OK if they both point to the same symbol 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (old->link() == pNew.link()) { 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* Fall through */ 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case MDEF: { /* multiple definition error. */ 173affc150dc44fab1911775a49636d0ce85333b634Zonr Chang error(diag::multiple_definitions) << pNew.name(); 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case REFC: { /* Mark indirect symbol referenced and then CYCLE. */ 177affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (NULL == old->link()) { 178affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::indirect_refer_to_inexist) << old->name(); 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old = old->link(); 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao col = getOrdinate(*old); 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao cycle = true; 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 187affc150dc44fab1911775a49636d0ce85333b634Zonr Chang default: { 188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang error(diag::undefined_situation) << action << old->name() << pNew.name(); 189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return false; 190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } // end of the big switch (action) 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } while(cycle); 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return true; 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 196