diff options
Diffstat (limited to 'lib/Core/IRBuilder.cpp')
-rw-r--r-- | lib/Core/IRBuilder.cpp | 208 |
1 files changed, 200 insertions, 8 deletions
diff --git a/lib/Core/IRBuilder.cpp b/lib/Core/IRBuilder.cpp index 5472db0..549aa8d 100644 --- a/lib/Core/IRBuilder.cpp +++ b/lib/Core/IRBuilder.cpp @@ -83,7 +83,7 @@ LDFileFormat::Kind GetELFSectionKind(uint32_t pType, const char* pName) return LDFileFormat::MetaData; } -bool shouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig) +bool ShouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig) { // forced local symbol matches all rules: // 1. We are not doing incremental linking. @@ -333,7 +333,7 @@ EhFrame* IRBuilder::CreateEhFrame(LDSection& pSection) { assert(!pSection.hasEhFrame() && "pSection already has eh_frame."); - EhFrame* eh_frame = new EhFrame(pSection); + EhFrame* eh_frame = EhFrame::Create(pSection); pSection.setEhFrame(eh_frame); return eh_frame; } @@ -471,13 +471,14 @@ LDSymbol* IRBuilder::AddSymbol(Input& pInput, return input_sym; } case Input::DynObj: { - return addSymbolFromDynObj(name, pType, pDesc, pBind, pSize, pValue, pVis); + return addSymbolFromDynObj(pInput, name, pType, pDesc, pBind, pSize, pValue, pVis); } default: { return NULL; break; } } + return NULL; } LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName, @@ -564,7 +565,7 @@ LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName, // No matter the symbol is already in the output or not, add it if it // should be forcefully set local. - if (shouldForceLocal(*resolved_result.info, m_Config)) + if (ShouldForceLocal(*resolved_result.info, m_Config)) m_Module.getSymbolTable().forceLocal(*output_sym); else { // the symbol should not be forcefully local. @@ -572,8 +573,8 @@ LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName, } } else if (resolved_result.overriden) { - if (!shouldForceLocal(old_info, m_Config) || - !shouldForceLocal(*resolved_result.info, m_Config)) { + if (!ShouldForceLocal(old_info, m_Config) || + !ShouldForceLocal(*resolved_result.info, m_Config)) { // If the old info and the new info are both forcefully local, then // we should keep the output_sym in forcefully local category. Else, // we should re-sort the output_sym @@ -585,7 +586,8 @@ LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName, return input_sym; } -LDSymbol* IRBuilder::addSymbolFromDynObj(const std::string& pName, +LDSymbol* IRBuilder::addSymbolFromDynObj(Input& pInput, + const std::string& pName, ResolveInfo::Type pType, ResolveInfo::Desc pDesc, ResolveInfo::Binding pBinding, @@ -619,6 +621,9 @@ LDSymbol* IRBuilder::addSymbolFromDynObj(const std::string& pName, // the return ResolveInfo should not NULL assert(NULL != resolved_result.info); + if (resolved_result.overriden || !resolved_result.existent) + pInput.setNeeded(); + // create a LDSymbol for the input file. LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info); input_sym->setFragmentRef(FragmentRef::Null()); @@ -638,7 +643,7 @@ LDSymbol* IRBuilder::addSymbolFromDynObj(const std::string& pName, // After symbol resolution, visibility is changed to the most restrict one. // If we are not doing incremental linking, then any symbol with hidden // or internal visibility is forcefully set as a local symbol. - if (shouldForceLocal(*resolved_result.info, m_Config)) { + if (ShouldForceLocal(*resolved_result.info, m_Config)) { m_Module.getSymbolTable().forceLocal(*output_sym); } } @@ -674,3 +679,190 @@ Relocation* IRBuilder::AddRelocation(LDSection& pSection, return relocation; } +/// AddSymbol - define an output symbol and override it immediately +template<> LDSymbol* +IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( + const llvm::StringRef& pName, + ResolveInfo::Type pType, + ResolveInfo::Desc pDesc, + ResolveInfo::Binding pBinding, + ResolveInfo::SizeType pSize, + LDSymbol::ValueType pValue, + FragmentRef* pFragmentRef, + ResolveInfo::Visibility pVisibility) +{ + ResolveInfo* info = m_Module.getNamePool().findInfo(pName); + LDSymbol* output_sym = NULL; + if (NULL == info) { + // the symbol is not in the pool, create a new one. + // create a ResolveInfo + Resolver::Result result; + m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, + pBinding, pSize, pVisibility, + NULL, result); + assert(!result.existent); + + // create a output LDSymbol + output_sym = LDSymbol::Create(*result.info); + result.info->setSymPtr(output_sym); + + if (ShouldForceLocal(*result.info, m_Config)) + m_Module.getSymbolTable().forceLocal(*output_sym); + else + m_Module.getSymbolTable().add(*output_sym); + } + else { + // the symbol is already in the pool, override it + ResolveInfo old_info; + old_info.override(*info); + + info->setRegular(); + info->setType(pType); + info->setDesc(pDesc); + info->setBinding(pBinding); + info->setVisibility(pVisibility); + info->setIsSymbol(true); + info->setSize(pSize); + + output_sym = info->outSymbol(); + if (NULL != output_sym) + m_Module.getSymbolTable().arrange(*output_sym, old_info); + else { + // create a output LDSymbol + output_sym = LDSymbol::Create(*info); + info->setSymPtr(output_sym); + + m_Module.getSymbolTable().add(*output_sym); + } + } + + if (NULL != output_sym) { + output_sym->setFragmentRef(pFragmentRef); + output_sym->setValue(pValue); + } + + return output_sym; +} + +/// AddSymbol - define an output symbol and override it immediately +template<> LDSymbol* +IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>( + const llvm::StringRef& pName, + ResolveInfo::Type pType, + ResolveInfo::Desc pDesc, + ResolveInfo::Binding pBinding, + ResolveInfo::SizeType pSize, + LDSymbol::ValueType pValue, + FragmentRef* pFragmentRef, + ResolveInfo::Visibility pVisibility) +{ + ResolveInfo* info = m_Module.getNamePool().findInfo(pName); + + if (NULL == info || !(info->isUndef() || info->isDyn())) { + // only undefined symbol and dynamic symbol can make a reference. + return NULL; + } + + // the symbol is already in the pool, override it + ResolveInfo old_info; + old_info.override(*info); + + info->setRegular(); + info->setType(pType); + info->setDesc(pDesc); + info->setBinding(pBinding); + info->setVisibility(pVisibility); + info->setIsSymbol(true); + info->setSize(pSize); + + LDSymbol* output_sym = info->outSymbol(); + if (NULL != output_sym) { + output_sym->setFragmentRef(pFragmentRef); + output_sym->setValue(pValue); + m_Module.getSymbolTable().arrange(*output_sym, old_info); + } + else { + // create a output LDSymbol + output_sym = LDSymbol::Create(*info); + info->setSymPtr(output_sym); + + m_Module.getSymbolTable().add(*output_sym); + } + + return output_sym; +} + +/// AddSymbol - define an output symbol and resolve it +/// immediately +template<> LDSymbol* +IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( + const llvm::StringRef& pName, + ResolveInfo::Type pType, + ResolveInfo::Desc pDesc, + ResolveInfo::Binding pBinding, + ResolveInfo::SizeType pSize, + LDSymbol::ValueType pValue, + FragmentRef* pFragmentRef, + ResolveInfo::Visibility pVisibility) +{ + // Result is <info, existent, override> + Resolver::Result result; + ResolveInfo old_info; + m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding, + pSize, pVisibility, + &old_info, result); + + LDSymbol* output_sym = result.info->outSymbol(); + bool has_output_sym = (NULL != output_sym); + + if (!result.existent || !has_output_sym) { + output_sym = LDSymbol::Create(*result.info); + result.info->setSymPtr(output_sym); + } + + if (result.overriden || !has_output_sym) { + output_sym->setFragmentRef(pFragmentRef); + output_sym->setValue(pValue); + } + + // After symbol resolution, the visibility is changed to the most restrict. + // arrange the output position + if (ShouldForceLocal(*result.info, m_Config)) + m_Module.getSymbolTable().forceLocal(*output_sym); + else if (has_output_sym) + m_Module.getSymbolTable().arrange(*output_sym, old_info); + else + m_Module.getSymbolTable().add(*output_sym); + + return output_sym; +} + +/// defineSymbol - define an output symbol and resolve it immediately. +template<> LDSymbol* +IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( + const llvm::StringRef& pName, + ResolveInfo::Type pType, + ResolveInfo::Desc pDesc, + ResolveInfo::Binding pBinding, + ResolveInfo::SizeType pSize, + LDSymbol::ValueType pValue, + FragmentRef* pFragmentRef, + ResolveInfo::Visibility pVisibility) +{ + ResolveInfo* info = m_Module.getNamePool().findInfo(pName); + + if (NULL == info || !(info->isUndef() || info->isDyn())) { + // only undefined symbol and dynamic symbol can make a reference. + return NULL; + } + + return AddSymbol<Force, Resolve>(pName, + pType, + pDesc, + pBinding, + pSize, + pValue, + pFragmentRef, + pVisibility); +} + |