//===- IRBuilder.cpp ------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include <mcld/IRBuilder.h> #include <mcld/LD/ELFReader.h> #include <mcld/Object/ObjectBuilder.h> #include <mcld/LD/SectionData.h> #include <mcld/LD/EhFrame.h> #include <mcld/LD/RelocData.h> #include <mcld/Support/MsgHandling.h> #include <mcld/Fragment/FragmentRef.h> using namespace mcld; //===----------------------------------------------------------------------===// // Helper Functions //===----------------------------------------------------------------------===// LDFileFormat::Kind GetELFSectionKind(uint32_t pType, const char* pName) { // name rules llvm::StringRef name(pName); if (name.startswith(".debug") || name.startswith(".zdebug") || name.startswith(".gnu.linkonce.wi.") || name.startswith(".line") || name.startswith(".stab")) return LDFileFormat::Debug; if (name.startswith(".comment")) return LDFileFormat::MetaData; if (name.startswith(".interp") || name.startswith(".dynamic")) return LDFileFormat::Note; if (name.startswith(".eh_frame")) return LDFileFormat::EhFrame; if (name.startswith(".eh_frame_hdr")) return LDFileFormat::EhFrameHdr; if (name.startswith(".gcc_except_table")) return LDFileFormat::GCCExceptTable; if (name.startswith(".note.GNU-stack")) return LDFileFormat::StackNote; // type rules switch(pType) { case llvm::ELF::SHT_NULL: return LDFileFormat::Null; case llvm::ELF::SHT_INIT_ARRAY: case llvm::ELF::SHT_FINI_ARRAY: case llvm::ELF::SHT_PREINIT_ARRAY: case llvm::ELF::SHT_PROGBITS: return LDFileFormat::Regular; case llvm::ELF::SHT_SYMTAB: case llvm::ELF::SHT_DYNSYM: case llvm::ELF::SHT_STRTAB: case llvm::ELF::SHT_HASH: case llvm::ELF::SHT_DYNAMIC: return LDFileFormat::NamePool; case llvm::ELF::SHT_RELA: case llvm::ELF::SHT_REL: return LDFileFormat::Relocation; case llvm::ELF::SHT_NOBITS: return LDFileFormat::BSS; case llvm::ELF::SHT_NOTE: return LDFileFormat::Note; case llvm::ELF::SHT_GROUP: return LDFileFormat::Group; case llvm::ELF::SHT_GNU_versym: case llvm::ELF::SHT_GNU_verdef: case llvm::ELF::SHT_GNU_verneed: return LDFileFormat::Version; case llvm::ELF::SHT_SHLIB: return LDFileFormat::Target; default: if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) || (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) || (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER)) return LDFileFormat::Target; fatal(diag::err_unsupported_section) << pName << pType; } return LDFileFormat::MetaData; } bool ShouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig) { // forced local symbol matches all rules: // 1. We are not doing incremental linking. // 2. The symbol is with Hidden or Internal visibility. // 3. The symbol should be global or weak. Otherwise, local symbol is local. // 4. The symbol is defined or common if (LinkerConfig::Object != pConfig.codeGenType() && (pInfo.visibility() == ResolveInfo::Hidden || pInfo.visibility() == ResolveInfo::Internal) && (pInfo.isGlobal() || pInfo.isWeak()) && (pInfo.isDefine() || pInfo.isCommon())) return true; return false; } //===----------------------------------------------------------------------===// // IRBuilder //===----------------------------------------------------------------------===// IRBuilder::IRBuilder(Module& pModule, const LinkerConfig& pConfig) : m_Module(pModule), m_Config(pConfig), m_InputBuilder(pConfig) { m_InputBuilder.setCurrentTree(m_Module.getInputTree()); } IRBuilder::~IRBuilder() { } /// CreateInput - To create an input file and append it to the input tree. Input* IRBuilder::CreateInput(const std::string& pName, const sys::fs::Path& pPath, Input::Type pType) { if (Input::Unknown == pType) return ReadInput(pName, pPath); m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, pType); Input* input = *m_InputBuilder.getCurrentNode(); if (!input->hasContext()) m_InputBuilder.setContext(*input, false); return input; } /// ReadInput - To read an input file and append it to the input tree. Input* IRBuilder::ReadInput(const std::string& pName, const sys::fs::Path& pPath) { m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, Input::Unknown); Input* input = *m_InputBuilder.getCurrentNode(); if (!input->hasContext()) m_InputBuilder.setContext(*input); if (!input->hasMemArea()) m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System); return input; } /// ReadInput - To read an input file and append it to the input tree. Input* IRBuilder::ReadInput(const std::string& pNameSpec) { const sys::fs::Path* path = NULL; // find out the real path of the namespec. if (m_InputBuilder.getConstraint().isSharedSystem()) { // In the system with shared object support, we can find both archive // and shared object. if (m_InputBuilder.getAttributes().isStatic()) { // with --static, we must search an archive. path = m_Config.options().directories().find(pNameSpec, Input::Archive); } else { // otherwise, with --Bdynamic, we can find either an archive or a // shared object. path = m_Config.options().directories().find(pNameSpec, Input::DynObj); } } else { // In the system without shared object support, we only look for an archive path = m_Config.options().directories().find(pNameSpec, Input::Archive); } if (NULL == path) { fatal(diag::err_cannot_find_namespec) << pNameSpec; return NULL; } m_InputBuilder.createNode<InputTree::Positional>(pNameSpec, *path); Input* input = *m_InputBuilder.getCurrentNode(); if (!input->hasContext()) m_InputBuilder.setContext(*input); if (!input->hasMemArea()) m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System); return input; } /// ReadInput - To read an input file and append it to the input tree. Input* IRBuilder::ReadInput(raw_mem_ostream& pMemOStream) { Input* input = NULL; if (pMemOStream.getMemoryArea().hasHandler()) { m_InputBuilder.createNode<InputTree::Positional>( "memory ostream", pMemOStream.getMemoryArea().handler()->path()); input = *m_InputBuilder.getCurrentNode(); m_InputBuilder.setContext(*input); input->setMemArea(&pMemOStream.getMemoryArea()); } else { m_InputBuilder.createNode<InputTree::Positional>("memory ostream", "NAN"); input = *m_InputBuilder.getCurrentNode(); m_InputBuilder.setContext(*input, false); input->setMemArea(&pMemOStream.getMemoryArea()); } return input; } /// ReadInput - To read an input file and append it to the input tree. Input* IRBuilder::ReadInput(FileHandle& pFileHandle) { m_InputBuilder.createNode<InputTree::Positional>("file handler", pFileHandle.path()); Input* input = *m_InputBuilder.getCurrentNode(); if (pFileHandle.path().empty()) { m_InputBuilder.setContext(*input, false); m_InputBuilder.setMemory(*input, pFileHandle.handler(), FileHandle::ReadOnly); } else { m_InputBuilder.setContext(*input, true); m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System); } return input; } /// ReadInput - To read an input file and append it to the input tree. Input* IRBuilder::ReadInput(const std::string& pName, void* pRawMemory, size_t pSize) { m_InputBuilder.createNode<InputTree::Positional>(pName, "NAN"); Input* input = *m_InputBuilder.getCurrentNode(); m_InputBuilder.setContext(*input, false); m_InputBuilder.setMemory(*input, pRawMemory, pSize); return input; } bool IRBuilder::StartGroup() { if (m_InputBuilder.isInGroup()) { fatal(diag::fatal_forbid_nest_group); return false; } m_InputBuilder.enterGroup(); return true; } bool IRBuilder::EndGroup() { m_InputBuilder.exitGroup(); return true; } void IRBuilder::WholeArchive() { m_InputBuilder.getAttributes().setWholeArchive(); } void IRBuilder::NoWholeArchive() { m_InputBuilder.getAttributes().unsetWholeArchive(); } void IRBuilder::AsNeeded() { m_InputBuilder.getAttributes().setAsNeeded(); } void IRBuilder::NoAsNeeded() { m_InputBuilder.getAttributes().unsetAsNeeded(); } void IRBuilder::CopyDTNeeded() { m_InputBuilder.getAttributes().setAddNeeded(); } void IRBuilder::NoCopyDTNeeded() { m_InputBuilder.getAttributes().unsetAddNeeded(); } void IRBuilder::AgainstShared() { m_InputBuilder.getAttributes().setDynamic(); } void IRBuilder::AgainstStatic() { m_InputBuilder.getAttributes().setStatic(); } LDSection* IRBuilder::CreateELFHeader(Input& pInput, const std::string& pName, uint32_t pType, uint32_t pFlag, uint32_t pAlign) { // Create section header LDFileFormat::Kind kind = GetELFSectionKind(pType, pName.c_str()); LDSection* header = LDSection::Create(pName, kind, pType, pFlag); header->setAlign(pAlign); // Append section header in input pInput.context()->appendSection(*header); return header; } /// CreateSectionData - To create a section data for given pSection. SectionData* IRBuilder::CreateSectionData(LDSection& pSection) { assert(!pSection.hasSectionData() && "pSection already has section data."); SectionData* sect_data = SectionData::Create(pSection); pSection.setSectionData(sect_data); return sect_data; } /// CreateRelocData - To create a relocation data for given pSection. RelocData* IRBuilder::CreateRelocData(LDSection &pSection) { assert(!pSection.hasRelocData() && "pSection already has relocation data."); RelocData* reloc_data = RelocData::Create(pSection); pSection.setRelocData(reloc_data); return reloc_data; } /// CreateEhFrame - To create a eh_frame for given pSection EhFrame* IRBuilder::CreateEhFrame(LDSection& pSection) { assert(!pSection.hasEhFrame() && "pSection already has eh_frame."); EhFrame* eh_frame = EhFrame::Create(pSection); pSection.setEhFrame(eh_frame); return eh_frame; } /// CreateBSS - To create a bss section for given pSection SectionData* IRBuilder::CreateBSS(LDSection& pSection) { assert(!pSection.hasSectionData() && "pSection already has section data."); assert((pSection.kind() == LDFileFormat::BSS) && "pSection is not a BSS section."); SectionData* sect_data = SectionData::Create(pSection); pSection.setSectionData(sect_data); /* value, valsize, size*/ FillFragment* frag = new FillFragment(0x0, 1, pSection.size()); ObjectBuilder::AppendFragment(*frag, *sect_data); return sect_data; } /// CreateRegion - To create a region fragment in the input file. Fragment* IRBuilder::CreateRegion(Input& pInput, size_t pOffset, size_t pLength) { if (!pInput.hasMemArea()) { fatal(diag::fatal_cannot_read_input) << pInput.path(); return NULL; } if (0 == pLength) return new FillFragment(0x0, 0, 0); MemoryRegion* region = pInput.memArea()->request(pOffset, pLength); if (NULL == region) return new FillFragment(0x0, 0, 0); return new RegionFragment(*region); } /// CreateRegion - To create a region fragment wrapping the given memory Fragment* IRBuilder::CreateRegion(void* pMemory, size_t pLength) { if (0 == pLength) return new FillFragment(0x0, 0, 0); MemoryRegion* region = MemoryRegion::Create(pMemory, pLength); if (NULL == region) return new FillFragment(0x0, 0, 0); return new RegionFragment(*region); } /// AppendFragment - To append pFrag to the given SectionData pSD uint64_t IRBuilder::AppendFragment(Fragment& pFrag, SectionData& pSD) { uint64_t size = ObjectBuilder::AppendFragment(pFrag, pSD, pSD.getSection().align()); pSD.getSection().setSize(pSD.getSection().size() + size); return size; } /// AppendRelocation - To append an relocation to the given RelocData pRD. void IRBuilder::AppendRelocation(Relocation& pRelocation, RelocData& pRD) { pRD.append(pRelocation); } /// AppendEhFrame - To append a fragment to EhFrame. uint64_t IRBuilder::AppendEhFrame(Fragment& pFrag, EhFrame& pEhFrame) { uint64_t size = ObjectBuilder::AppendFragment(pFrag, pEhFrame.getSectionData(), pEhFrame.getSection().align()); pEhFrame.getSection().setSize(pEhFrame.getSection().size() + size); return size; } /// AppendEhFrame - To append a FDE to the given EhFrame pEhFram. uint64_t IRBuilder::AppendEhFrame(EhFrame::FDE& pFDE, EhFrame& pEhFrame) { pEhFrame.addFDE(pFDE); pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pFDE.size()); return pFDE.size(); } /// AppendEhFrame - To append a CIE to the given EhFrame pEhFram. uint64_t IRBuilder::AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame) { pEhFrame.addCIE(pCIE); pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pCIE.size()); return pCIE.size(); } /// AddSymbol - To add a symbol in the input file and resolve the symbol /// immediately LDSymbol* IRBuilder::AddSymbol(Input& pInput, const std::string& pName, ResolveInfo::Type pType, ResolveInfo::Desc pDesc, ResolveInfo::Binding pBind, ResolveInfo::SizeType pSize, LDSymbol::ValueType pValue, LDSection* pSection, ResolveInfo::Visibility pVis) { // rename symbols std::string name = pName; if (!m_Config.scripts().renameMap().empty() && ResolveInfo::Undefined == pDesc) { // If the renameMap is not empty, some symbols should be renamed. // --wrap and --portable defines the symbol rename map. ScriptOptions::SymbolRenameMap::const_iterator renameSym = m_Config.scripts().renameMap().find(pName); if (renameSym != m_Config.scripts().renameMap().end()) name = renameSym.getEntry()->value(); } switch (pInput.type()) { case Input::Object: { FragmentRef* frag = NULL; if (NULL == pSection || ResolveInfo::Undefined == pDesc || ResolveInfo::Common == pDesc || ResolveInfo::Absolute == pBind || LDFileFormat::Ignore == pSection->kind() || LDFileFormat::Group == pSection->kind()) frag = FragmentRef::Null(); else frag = FragmentRef::Create(*pSection, pValue); LDSymbol* input_sym = addSymbolFromObject(name, pType, pDesc, pBind, pSize, pValue, frag, pVis); pInput.context()->addSymbol(input_sym); return input_sym; } case Input::DynObj: { return addSymbolFromDynObj(pInput, name, pType, pDesc, pBind, pSize, pValue, pVis); } default: { return NULL; break; } } return NULL; } LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName, ResolveInfo::Type pType, ResolveInfo::Desc pDesc, ResolveInfo::Binding pBinding, ResolveInfo::SizeType pSize, LDSymbol::ValueType pValue, FragmentRef* pFragmentRef, ResolveInfo::Visibility pVisibility) { // Step 1. calculate a Resolver::Result // resolved_result is a triple <resolved_info, existent, override> Resolver::Result resolved_result; ResolveInfo old_info; // used for arrange output symbols if (pBinding == ResolveInfo::Local) { // if the symbol is a local symbol, create a LDSymbol for input, but do not // resolve them. resolved_result.info = m_Module.getNamePool().createSymbol(pName, false, pType, pDesc, pBinding, pSize, pVisibility); // No matter if there is a symbol with the same name, insert the symbol // into output symbol table. So, we let the existent false. resolved_result.existent = false; resolved_result.overriden = true; } else { // if the symbol is not local, insert and resolve it immediately m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding, pSize, pVisibility, &old_info, resolved_result); } // the return ResolveInfo should not NULL assert(NULL != resolved_result.info); /// Step 2. create an input LDSymbol. // create a LDSymbol for the input file. LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info); input_sym->setFragmentRef(pFragmentRef); input_sym->setValue(pValue); // Step 3. Set up corresponding output LDSymbol LDSymbol* output_sym = resolved_result.info->outSymbol(); bool has_output_sym = (NULL != output_sym); if (!resolved_result.existent || !has_output_sym) { // it is a new symbol, the output_sym should be NULL. assert(NULL == output_sym); if (pType == ResolveInfo::Section) { // if it is a section symbol, its output LDSymbol is the input LDSymbol. output_sym = input_sym; } else { // if it is a new symbol, create a LDSymbol for the output output_sym = LDSymbol::Create(*resolved_result.info); } resolved_result.info->setSymPtr(output_sym); } if (resolved_result.overriden || !has_output_sym) { // symbol can be overriden only if it exists. assert(output_sym != NULL); // should override output LDSymbol output_sym->setFragmentRef(pFragmentRef); output_sym->setValue(pValue); } // Step 4. Adjust the position of output LDSymbol. // After symbol resolution, visibility is changed to the most restrict one. // we need to arrange its position in the output symbol. We arrange the // positions by sorting symbols in SymbolCategory. if (pType != ResolveInfo::Section) { if (!has_output_sym) { // We merge sections when reading them. So we do not need to output symbols // with section type // 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)) m_Module.getSymbolTable().forceLocal(*output_sym); else { // the symbol should not be forcefully local. m_Module.getSymbolTable().add(*output_sym); } } else if (resolved_result.overriden) { 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 m_Module.getSymbolTable().arrange(*output_sym, old_info); } } } return input_sym; } LDSymbol* IRBuilder::addSymbolFromDynObj(Input& pInput, const std::string& pName, ResolveInfo::Type pType, ResolveInfo::Desc pDesc, ResolveInfo::Binding pBinding, ResolveInfo::SizeType pSize, LDSymbol::ValueType pValue, ResolveInfo::Visibility pVisibility) { // We don't need sections of dynamic objects. So we ignore section symbols. if (pType == ResolveInfo::Section) return NULL; // ignore symbols with local binding or that have internal or hidden // visibility if (pBinding == ResolveInfo::Local || pVisibility == ResolveInfo::Internal || pVisibility == ResolveInfo::Hidden) return NULL; // A protected symbol in a shared library must be treated as a // normal symbol when viewed from outside the shared library. if (pVisibility == ResolveInfo::Protected) pVisibility = ResolveInfo::Default; // insert symbol and resolve it immediately // resolved_result is a triple <resolved_info, existent, override> Resolver::Result resolved_result; m_Module.getNamePool().insertSymbol(pName, true, pType, pDesc, pBinding, pSize, pVisibility, NULL, resolved_result); // 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()); input_sym->setValue(pValue); LDSymbol* output_sym = NULL; if (!resolved_result.existent) { // we get a new symbol, leave it as NULL resolved_result.info->setSymPtr(NULL); } else { // we saw the symbol before, but the output_sym still may be NULL. output_sym = resolved_result.info->outSymbol(); } if (output_sym != NULL) { // 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)) { m_Module.getSymbolTable().forceLocal(*output_sym); } } return input_sym; } /// AddRelocation - add a relocation entry /// /// All symbols should be read and resolved before calling this function. Relocation* IRBuilder::AddRelocation(LDSection& pSection, Relocation::Type pType, LDSymbol& pSym, uint32_t pOffset, Relocation::Address pAddend) { // FIXME: we should dicard sections and symbols first instead // if the symbol is in the discarded input section, then we also need to // discard this relocation. ResolveInfo* resolve_info = pSym.resolveInfo(); if (!pSym.hasFragRef() && ResolveInfo::Section == resolve_info->type() && ResolveInfo::Undefined == resolve_info->desc()) return NULL; FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset); Relocation* relocation = Relocation::Create(pType, *frag_ref, pAddend); relocation->setSymInfo(resolve_info); pSection.getRelocData()->append(*relocation); 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); }