StaticResolver.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/StaticResolver.h" 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Demangle.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//========================== 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// StaticResolver 1937b74a387bb3993387029859c2d9d051c41c724eStephen HinesStaticResolver::~StaticResolver() { 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 22affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool StaticResolver::resolve(ResolveInfo& __restrict__ pOld, 23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const ResolveInfo& __restrict__ pNew, 2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool& pOverride, 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol::ValueType pValue) const { 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) 3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Is -> all kind of indirect 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines static const enum LinkAction link_action[LAST_ORD][LAST_ORD] = { 3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* new\old U w_U d_U wd_U D w_D d_D wd_D C w_C, Cs, Is */ // NOLINT 3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* U */ {NOACT, UND, UND, UND, NOACT, NOACT, DUND, DUND, NOACT, NOACT, NOACT, REFC }, // NOLINT 3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* w_U */ {NOACT, NOACT, NOACT, WEAK, NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC }, // NOLINT 3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* d_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, // NOLINT 3737b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* wd_U */ {NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, // NOLINT 3837b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* D */ {DEF, DEF, DEF, DEF, MDEF, DEF, DEF, DEF, CDEF, CDEF, CDEF, MDEF }, // NOLINT 3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* w_D */ {DEFW, DEFW, DEFW, DEFW, NOACT, NOACT, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT}, // NOLINT 4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* d_D */ {MDEFD, MDEFD, DEFD, DEFD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF }, // NOLINT 4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT}, // NOLINT 4237b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* C */ {COM, COM, COM, COM, CREF, COM, COM, COM, MBIG, COM, BIG, REFC }, // NOLINT 4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* w_C */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC }, // NOLINT 4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* Cs */ {COM, COM, COM, COM, NOACT, NOACT, NOACT, NOACT, MBIG, MBIG, MBIG, REFC }, // NOLINT 4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* Is */ {IND, IND, IND, IND, MDEF, IND, IND, IND, CIND, CIND, CIND, MIND } // NOLINT 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao }; 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Special cases: 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * when a dynamic defined symbol meets a dynamic weak defined symbol, act 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // noting. 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * when a undefined symbol meets a dynamic defined symbol, override by 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // dynamic defined first, then recover back to undefined symbol later. 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * when a dynamic defined symbol meets a undefined symbol or a weak 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // undefined symbol, do not override, instead of marking. 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * When a undefined symbol meets a dynamic defined symbol or a weak 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // undefined symbol meets a dynamic defined symbol, should override. 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // * When a common symbol meets a weak common symbol, adjust the size of 5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines // common symbol. 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int row = getOrdinate(pNew); 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int col = getOrdinate(pOld); 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool cycle = false; 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* old = &pOld; 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao LinkAction action; 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao do { 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao cycle = false; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao action = link_action[row][col]; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7137b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (action) { 7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines case FAIL: { /* abort. */ 7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::fail_sym_resolution) << __FILE__ << __LINE__ 7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines << "mclinker@googlegroups.com"; 75affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return false; 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines case NOACT: { /* no action. */ 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines case UND: /* override by symbol undefined symbol. */ 8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines case WEAK: /* override by symbol weak undefined. */ 8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines case DEF: /* override by symbol defined. */ 8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines case DEFW: /* override by symbol weak defined. */ 8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines case DEFD: /* override by symbol dynamic defined. */ 8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines case DEFWD: /* override by symbol dynamic weak defined. */ 8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines case COM: { /* override by symbol common defined. */ 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->override(pNew); 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines case MDEFD: /* mark symbol dynamic defined. */ 9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines case MDEFWD: { /* mark symbol dynamic weak defined. */ 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t binding = old->binding(); 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->override(pNew); 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setBinding(binding); 98affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::mark_dynamic_defined) << old->name(); 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DUND: 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case DUNDW: { 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 105affc150dc44fab1911775a49636d0ce85333b634Zonr Chang old->setDynamic(); 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines case CREF: { /* Possibly warn about common reference to defined symbol. */ 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // A common symbol does not override a definition. 111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::comm_refer_to_define) << old->name(); 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines case CDEF: { /* redefine existing common symbol. */ 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // We've seen a common symbol and now we see a definition. The 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // definition overrides. 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // 11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines // NOTE: m_Mesg uses 'name' instead of `name' for being compatible to 12037b74a387bb3993387029859c2d9d051c41c724eStephen Hines // GNU ld. 121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ignore(diag::redefine_common) << old->name(); 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->override(pNew); 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines case BIG: { /* override by symbol common using largest size. */ 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (old->size() < pNew.size()) 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setSize(pNew.size()); 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideAttributes(pNew); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines case MBIG: { /* mark common symbol by larger size. */ 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (old->size() < pNew.size()) 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setSize(pNew.size()); 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->overrideVisibility(pNew); 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines case CIND: { /* mark indirect symbol from existing common symbol. */ 14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines ignore(diag::indirect_refer_to_common) << old->name(); 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* Fall through */ 14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines case IND: { /* override by indirect symbol. */ 14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pNew.link() == NULL) { 147affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::indirect_refer_to_inexist) << pNew.name(); 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /** Should detect the loop of indirect symbol during file reading **/ 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if (pNew.link()->isIndirect() && pNew.link()->link() == &pNew) { 15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines // m_Mesg = "indirect symbol `"+pNew.name()+"' to 15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines // `"+pNew.link()->name()+"' is a loop."; 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // return Resolver::Abort; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao //} 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // change the old symbol to the indirect symbol 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old->setLink(pNew.link()); 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = true; 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines case MIND: { /* multiple indirect symbols. */ 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // it is OK if they both point to the same symbol 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (old->link() == pNew.link()) { 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pOverride = false; 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /* Fall through */ 17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines case MDEF: { /* multiple definition error. */ 17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pOld.isDefine() && pNew.isDefine() && pOld.isAbsolute() && 17337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pNew.isAbsolute() && 17487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (pOld.desc() == pNew.desc() || pOld.desc() == ResolveInfo::NoType || 17587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pNew.desc() == ResolveInfo::NoType)) { 17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pOld.outSymbol()->value() == pValue) { 17787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pOverride = true; 17887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines old->override(pNew); 17987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines break; 18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } else { 1810dea6bc96bb52346737966839ac68644f7939f58Stephen Hines error(diag::multiple_absolute_definitions) 18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines << demangleName(pNew.name()) << pOld.outSymbol()->value() 1830dea6bc96bb52346737966839ac68644f7939f58Stephen Hines << pValue; 18487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines break; 18587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 1870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines 1880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines error(diag::multiple_definitions) << demangleName(pNew.name()); 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 19137b74a387bb3993387029859c2d9d051c41c724eStephen Hines case REFC: { /* Mark indirect symbol referenced and then CYCLE. */ 19237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (old->link() == NULL) { 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::indirect_refer_to_inexist) << old->name(); 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao old = old->link(); 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao col = getOrdinate(*old); 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao cycle = true; 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 202affc150dc44fab1911775a49636d0ce85333b634Zonr Chang default: { 20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines error(diag::undefined_situation) << action << old->name() 20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines << pNew.name(); 205affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return false; 206affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 20737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end of the big switch (action) 20837b74a387bb3993387029859c2d9d051c41c724eStephen Hines } while (cycle); 209affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return true; 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 21237b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 213