| //===- 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/Fragment/FragmentRef.h" |
| #include "mcld/LinkerScript.h" |
| #include "mcld/LD/DebugString.h" |
| #include "mcld/LD/EhFrame.h" |
| #include "mcld/LD/ELFReader.h" |
| #include "mcld/LD/LDContext.h" |
| #include "mcld/LD/RelocData.h" |
| #include "mcld/LD/SectionData.h" |
| #include "mcld/Object/ObjectBuilder.h" |
| #include "mcld/Support/ELF.h" |
| #include "mcld/Support/MemoryArea.h" |
| #include "mcld/Support/MsgHandling.h" |
| |
| #include <llvm/ADT/StringRef.h> |
| |
| namespace mcld { |
| |
| //===----------------------------------------------------------------------===// |
| // Helper Functions |
| //===----------------------------------------------------------------------===// |
| LDFileFormat::Kind GetELFSectionKind(uint32_t pType, |
| const char* pName, |
| uint32_t pFlag) { |
| if (pFlag & llvm::ELF::SHF_EXCLUDE) |
| return LDFileFormat::Exclude; |
| |
| if (pFlag & llvm::ELF::SHF_MASKPROC) |
| return LDFileFormat::Target; |
| |
| // name rules |
| llvm::StringRef name(pName); |
| if (name.startswith(".debug") || name.startswith(".zdebug") || |
| name.startswith(".line") || name.startswith(".stab")) { |
| if (name.startswith(".debug_str")) |
| return LDFileFormat::DebugString; |
| 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; |
| if (name.startswith(".gnu.linkonce")) |
| return LDFileFormat::LinkOnce; |
| |
| // 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: { |
| if ((pFlag & llvm::ELF::SHF_EXECINSTR) != 0) |
| return LDFileFormat::TEXT; |
| else |
| return LDFileFormat::DATA; |
| } |
| 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: |
| case llvm::ELF::SHT_SYMTAB_SHNDX: |
| 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; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // IRBuilder |
| //===----------------------------------------------------------------------===// |
| IRBuilder::IRBuilder(Module& pModule, const LinkerConfig& pConfig) |
| : m_Module(pModule), m_Config(pConfig), m_InputBuilder(pConfig) { |
| m_InputBuilder.setCurrentTree(m_Module.getInputTree()); |
| |
| // FIXME: where to set up Relocation? |
| Relocation::SetUp(m_Config); |
| } |
| |
| 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::OpenMode(FileHandle::ReadOnly), |
| FileHandle::Permission(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_Module.getScript().directories().find(pNameSpec, Input::Archive); |
| } else { |
| // otherwise, with --Bdynamic, we can find either an archive or a |
| // shared object. |
| path = m_Module.getScript().directories().find(pNameSpec, Input::DynObj); |
| } |
| } else { |
| // In the system without shared object support, we only look for an archive |
| path = m_Module.getScript().directories().find(pNameSpec, Input::Archive); |
| } |
| |
| if (path == NULL) { |
| 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::OpenMode(FileHandle::ReadOnly), |
| FileHandle::Permission(FileHandle::System)); |
| |
| 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); |
| } else { |
| m_InputBuilder.setContext(*input, true); |
| } |
| m_InputBuilder.setMemory(*input, FileHandle::OpenMode(FileHandle::ReadOnly), |
| FileHandle::Permission(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, sys::fs::Path("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(), pFlag); |
| 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; |
| } |
| |
| /// CreateDebugString - To create a DebugString for given pSection |
| DebugString* IRBuilder::CreateDebugString(LDSection& pSection) { |
| assert(!pSection.hasDebugString() && "pSection already has debug_str."); |
| |
| DebugString* debug_str = DebugString::Create(pSection); |
| pSection.setDebugString(debug_str); |
| return debug_str; |
| } |
| |
| /// 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); |
| |
| llvm::StringRef region = pInput.memArea()->request(pOffset, pLength); |
| 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); |
| |
| llvm::StringRef region(reinterpret_cast<const char*>(pMemory), pLength); |
| 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_Module.getScript().renameMap().empty() && |
| ResolveInfo::Undefined == pDesc) { |
| // If the renameMap is not empty, some symbols should be renamed. |
| // --wrap and --portable defines the symbol rename map. |
| const LinkerScript& script = m_Module.getScript(); |
| LinkerScript::SymbolRenameMap::const_iterator renameSym = |
| script.renameMap().find(pName); |
| if (script.renameMap().end() != renameSym) |
| name = renameSym.getEntry()->value(); |
| } |
| |
| // Fix up the visibility if object has no export set. |
| if (pInput.noExport() && (pDesc != ResolveInfo::Undefined)) { |
| if ((pVis == ResolveInfo::Default) || (pVis == ResolveInfo::Protected)) { |
| pVis = ResolveInfo::Hidden; |
| } |
| } |
| |
| switch (pInput.type()) { |
| case Input::Object: { |
| FragmentRef* frag = NULL; |
| if (pSection == NULL || 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, |
| pValue, |
| pVisibility, |
| &old_info, |
| resolved_result); |
| } |
| |
| // the return ResolveInfo should not NULL |
| assert(resolved_result.info != NULL); |
| |
| /// 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 = (output_sym != NULL); |
| if (!resolved_result.existent || !has_output_sym) { |
| // it is a new symbol, the output_sym should be NULL. |
| assert(output_sym == NULL); |
| |
| 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); |
| } |
| 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, |
| pValue, |
| pVisibility, |
| NULL, |
| resolved_result); |
| |
| // the return ResolveInfo should not NULL |
| assert(resolved_result.info != NULL); |
| |
| 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); |
| |
| // this symbol is seen in a dynamic object, set the InDyn flag |
| resolved_result.info->setInDyn(); |
| |
| if (!resolved_result.existent) { |
| // we get a new symbol, leave it as NULL |
| resolved_result.info->setSymPtr(NULL); |
| } |
| 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) { |
| FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset); |
| |
| Relocation* relocation = Relocation::Create(pType, *frag_ref, pAddend); |
| |
| relocation->setSymInfo(pSym.resolveInfo()); |
| pSection.getRelocData()->append(*relocation); |
| |
| return relocation; |
| } |
| |
| ResolveInfo* IRBuilder::CreateLocalSymbol(FragmentRef& pFragRef) { |
| // Create and add symbol to the name pool. |
| ResolveInfo* resolveInfo = |
| m_Module.getNamePool().createSymbol(/* pName */"", |
| /* pIsDyn */false, |
| ResolveInfo::Section, |
| ResolveInfo::Define, |
| ResolveInfo::Local, |
| /* pSize */0, |
| ResolveInfo::Hidden); |
| if (resolveInfo == nullptr) { |
| return nullptr; |
| } |
| |
| // Create input symbol. |
| LDSymbol* inputSym = LDSymbol::Create(*resolveInfo); |
| if (inputSym == nullptr) { |
| return nullptr; |
| } |
| |
| inputSym->setFragmentRef(FragmentRef::Create(*pFragRef.frag(), |
| pFragRef.offset())); |
| inputSym->setValue(/* pValue */0); |
| |
| // The output symbol is simply an alias to the input symbol. |
| resolveInfo->setSymPtr(inputSym); |
| |
| return resolveInfo; |
| } |
| |
| /// 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 (info == NULL) { |
| // 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, |
| pValue, |
| pVisibility, |
| NULL, |
| result); |
| assert(!result.existent); |
| |
| // create a output LDSymbol |
| output_sym = LDSymbol::Create(*result.info); |
| result.info->setSymPtr(output_sym); |
| |
| if (result.info->shouldForceLocal(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 (output_sym != NULL) |
| 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 (output_sym != NULL) { |
| 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 (info == NULL || !(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 (output_sym != NULL) { |
| 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, |
| pValue, |
| pVisibility, |
| &old_info, |
| result); |
| |
| LDSymbol* output_sym = result.info->outSymbol(); |
| bool has_output_sym = (output_sym != NULL); |
| |
| 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 (result.info->shouldForceLocal(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 (info == NULL || !(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); |
| } |
| |
| } // namespace mcld |