1//===- AArch64CA53ErratumStub.cpp -----------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "AArch64CA53ErratumStub.h" 11#include "AArch64InsnHelpers.h" 12#include "AArch64LDBackend.h" 13#include "AArch64RelocationHelpers.h" 14#include "AArch64Relocator.h" 15 16#include "mcld/Fragment/FragmentRef.h" 17#include "mcld/Fragment/Relocation.h" 18#include "mcld/IRBuilder.h" 19#include "mcld/LD/BranchIsland.h" 20#include "mcld/LD/LDSymbol.h" 21#include "mcld/LD/ResolveInfo.h" 22 23#include <llvm/ADT/StringExtras.h> 24#include <llvm/Support/ELF.h> 25 26#include <cassert> 27 28namespace mcld { 29 30//===----------------------------------------------------------------------===// 31// AArch64CA53ErratumStub 32//===----------------------------------------------------------------------===// 33const uint32_t AArch64CA53ErratumStub::TEMPLATE[] = { 34 0x00000000, // Placeholder for erratum insn 35 0x00000000, // Palceholder for branch instruction 36}; 37 38AArch64CA53ErratumStub::AArch64CA53ErratumStub() 39 : m_pData(NULL), 40 m_Name("erratum__prototype"), 41 m_Size(0x0) { 42 m_pData = TEMPLATE; 43 m_Size = sizeof(TEMPLATE); 44 addFixup(0x0, 0, AArch64Relocator::R_AARCH64_REWRITE_INSN); 45 addFixup(0x4, 0, llvm::ELF::R_AARCH64_JUMP26); 46} 47 48/// for doClone 49AArch64CA53ErratumStub::AArch64CA53ErratumStub(const uint32_t* pData, 50 size_t pSize, 51 const char* pName, 52 const_fixup_iterator pBegin, 53 const_fixup_iterator pEnd) 54 : m_pData(pData), 55 m_Name(pName), 56 m_Size(pSize) { 57 for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it) { 58 addFixup(**it); 59 } 60} 61 62AArch64CA53ErratumStub::~AArch64CA53ErratumStub() { 63} 64 65bool AArch64CA53ErratumStub::isMyDuty(const FragmentRef& pFragRef) const { 66 return false; 67} 68 69void AArch64CA53ErratumStub::applyFixup(FragmentRef& pSrcFragRef, 70 IRBuilder& pBuilder, 71 BranchIsland& pIsland) { 72 assert(isMyDuty(pSrcFragRef)); 73 74 // Build stub symbol name. 75 std::string sym_name("__"); 76 sym_name.append(name()) 77 .append(llvm::utohexstr(pIsland.numOfStubs())) 78 .append("@") 79 .append(pIsland.name()); 80 81 // Create LDSymbol for the stub. 82 LDSymbol* stub_sym = 83 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 84 sym_name, 85 ResolveInfo::NoType, 86 ResolveInfo::Define, 87 ResolveInfo::Local, 88 size(), 89 initSymValue(), 90 FragmentRef::Create(*this, initSymValue()), 91 ResolveInfo::Default); 92 setSymInfo(stub_sym->resolveInfo()); 93 94 // Create the target symbol of the stub to the next instruction of erratum 95 // pattarn. 96 FragmentRef* target = FragmentRef::Create(*pSrcFragRef.frag(), 97 pSrcFragRef.offset() + 98 getErratumInsnOffset() + 99 AArch64InsnHelpers::InsnSize); 100 ResolveInfo* target_info = pBuilder.CreateLocalSymbol(*target); 101 102 // Apply the fixups. 103 fixup_iterator it = fixup_begin(); 104 // Rewrite the first instruction as the erratum instruction. 105 Relocation* reloc = 106 Relocation::Create((*it)->type(), 107 *(FragmentRef::Create(*this, (*it)->offset())), 108 (*it)->addend()); 109 reloc->setSymInfo(target_info); 110 111 std::unique_ptr<unsigned[]> code(new unsigned[getErratumSequenceSize() / 4]); 112 pSrcFragRef.memcpy(code.get(), getErratumSequenceSize(), 0); 113 reloc->target() = 114 code[getErratumInsnOffset() / AArch64InsnHelpers::InsnSize]; 115 pIsland.addRelocation(*reloc); 116 117 // Construct the second instruction as a branch to target. 118 ++it; 119 reloc = Relocation::Create((*it)->type(), 120 *(FragmentRef::Create(*this, (*it)->offset())), 121 (*it)->addend()); 122 reloc->setSymInfo(target_info); 123 reloc->target() = AArch64InsnHelpers::buildBranchInsn(); 124 pIsland.addRelocation(*reloc); 125 126 assert((++it) == fixup_end()); 127} 128 129const std::string& AArch64CA53ErratumStub::name() const { 130 return m_Name; 131} 132 133const uint32_t* AArch64CA53ErratumStub::getData() const { 134 return m_pData; 135} 136 137const uint8_t* AArch64CA53ErratumStub::getContent() const { 138 return reinterpret_cast<const uint8_t*>(m_pData); 139} 140 141size_t AArch64CA53ErratumStub::size() const { 142 return m_Size; 143} 144 145size_t AArch64CA53ErratumStub::alignment() const { 146 return 8; 147} 148 149} // namespace mcld 150