| //===- Stub.cpp -----------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/Fragment/Stub.h" |
| |
| #include "mcld/IRBuilder.h" |
| #include "mcld/Fragment/Relocation.h" |
| #include "mcld/LD/BranchIsland.h" |
| #include "mcld/LD/ResolveInfo.h" |
| |
| #include <cassert> |
| |
| namespace mcld { |
| |
| Stub::Stub() : Fragment(Fragment::Stub), m_pSymInfo(NULL) { |
| } |
| |
| Stub::~Stub() { |
| for (fixup_iterator fixup = fixup_begin(); fixup != fixup_end(); ++fixup) |
| delete (*fixup); |
| } |
| |
| void Stub::setSymInfo(ResolveInfo* pSymInfo) { |
| m_pSymInfo = pSymInfo; |
| } |
| |
| void Stub::applyFixup(Relocation& pSrcReloc, |
| IRBuilder& pBuilder, |
| BranchIsland& pIsland) { |
| // build a name for stub symbol |
| std::string sym_name("__"); |
| sym_name.append(pSrcReloc.symInfo()->name()) |
| .append("_") |
| .append(name()) |
| .append("@") |
| .append(pIsland.name()); |
| |
| // create LDSymbol for the stub |
| LDSymbol* symbol = |
| pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( |
| sym_name, |
| ResolveInfo::Function, |
| ResolveInfo::Define, |
| ResolveInfo::Local, |
| size(), |
| initSymValue(), |
| FragmentRef::Create(*this, initSymValue()), |
| ResolveInfo::Default); |
| setSymInfo(symbol->resolveInfo()); |
| |
| // add relocations of this stub (i.e., set the branch target of the stub) |
| for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) { |
| Relocation* reloc = |
| Relocation::Create((*it)->type(), |
| *(FragmentRef::Create(*this, (*it)->offset())), |
| (*it)->addend()); |
| reloc->setSymInfo(pSrcReloc.symInfo()); |
| pIsland.addRelocation(*reloc); |
| } |
| } |
| |
| void Stub::applyFixup(FragmentRef& pSrcFragRef, |
| IRBuilder& pBuilder, |
| BranchIsland& pIsland) { |
| // If applying fixups is based on the source FragmentRef, each target stub |
| // probably should override this function. |
| assert(0 && "target stub should override this function"); |
| } |
| |
| void Stub::addFixup(DWord pOffset, SWord pAddend, Type pType) { |
| assert(pOffset < size()); |
| m_FixupList.push_back(new Fixup(pOffset, pAddend, pType)); |
| } |
| |
| void Stub::addFixup(const Fixup& pFixup) { |
| assert(pFixup.offset() < size()); |
| m_FixupList.push_back(new Fixup(pFixup)); |
| } |
| |
| } // namespace mcld |