//===- AArch64CA53ErratumStub.cpp -----------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "AArch64CA53ErratumStub.h" #include "AArch64InsnHelpers.h" #include "AArch64LDBackend.h" #include "AArch64RelocationHelpers.h" #include "AArch64Relocator.h" #include "mcld/Fragment/FragmentRef.h" #include "mcld/Fragment/Relocation.h" #include "mcld/IRBuilder.h" #include "mcld/LD/BranchIsland.h" #include "mcld/LD/LDSymbol.h" #include "mcld/LD/ResolveInfo.h" #include #include #include namespace mcld { //===----------------------------------------------------------------------===// // AArch64CA53ErratumStub //===----------------------------------------------------------------------===// const uint32_t AArch64CA53ErratumStub::TEMPLATE[] = { 0x00000000, // Placeholder for erratum insn 0x00000000, // Palceholder for branch instruction }; AArch64CA53ErratumStub::AArch64CA53ErratumStub() : m_pData(NULL), m_Name("erratum__prototype"), m_Size(0x0) { m_pData = TEMPLATE; m_Size = sizeof(TEMPLATE); addFixup(0x0, 0, AArch64Relocator::R_AARCH64_REWRITE_INSN); addFixup(0x4, 0, llvm::ELF::R_AARCH64_JUMP26); } /// for doClone AArch64CA53ErratumStub::AArch64CA53ErratumStub(const uint32_t* pData, size_t pSize, const char* pName, const_fixup_iterator pBegin, const_fixup_iterator pEnd) : m_pData(pData), m_Name(pName), m_Size(pSize) { for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it) { addFixup(**it); } } AArch64CA53ErratumStub::~AArch64CA53ErratumStub() { } bool AArch64CA53ErratumStub::isMyDuty(const FragmentRef& pFragRef) const { return false; } void AArch64CA53ErratumStub::applyFixup(FragmentRef& pSrcFragRef, IRBuilder& pBuilder, BranchIsland& pIsland) { assert(isMyDuty(pSrcFragRef)); // Build stub symbol name. std::string sym_name("__"); sym_name.append(name()) .append(llvm::utohexstr(pIsland.numOfStubs())) .append("@") .append(pIsland.name()); // Create LDSymbol for the stub. LDSymbol* stub_sym = pBuilder.AddSymbol( sym_name, ResolveInfo::NoType, ResolveInfo::Define, ResolveInfo::Local, size(), initSymValue(), FragmentRef::Create(*this, initSymValue()), ResolveInfo::Default); setSymInfo(stub_sym->resolveInfo()); // Create the target symbol of the stub to the next instruction of erratum // pattarn. FragmentRef* target = FragmentRef::Create(*pSrcFragRef.frag(), pSrcFragRef.offset() + getErratumInsnOffset() + AArch64InsnHelpers::InsnSize); ResolveInfo* target_info = pBuilder.CreateLocalSymbol(*target); // Apply the fixups. fixup_iterator it = fixup_begin(); // Rewrite the first instruction as the erratum instruction. Relocation* reloc = Relocation::Create((*it)->type(), *(FragmentRef::Create(*this, (*it)->offset())), (*it)->addend()); reloc->setSymInfo(target_info); std::unique_ptr code(new unsigned[getErratumSequenceSize() / 4]); pSrcFragRef.memcpy(code.get(), getErratumSequenceSize(), 0); reloc->target() = code[getErratumInsnOffset() / AArch64InsnHelpers::InsnSize]; pIsland.addRelocation(*reloc); // Construct the second instruction as a branch to target. ++it; reloc = Relocation::Create((*it)->type(), *(FragmentRef::Create(*this, (*it)->offset())), (*it)->addend()); reloc->setSymInfo(target_info); reloc->target() = AArch64InsnHelpers::buildBranchInsn(); pIsland.addRelocation(*reloc); assert((++it) == fixup_end()); } const std::string& AArch64CA53ErratumStub::name() const { return m_Name; } const uint32_t* AArch64CA53ErratumStub::getData() const { return m_pData; } const uint8_t* AArch64CA53ErratumStub::getContent() const { return reinterpret_cast(m_pData); } size_t AArch64CA53ErratumStub::size() const { return m_Size; } size_t AArch64CA53ErratumStub::alignment() const { return 8; } } // namespace mcld