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 28 namespace mcld { 29 30 //===----------------------------------------------------------------------===// 31 // AArch64CA53ErratumStub 32 //===----------------------------------------------------------------------===// 33 const uint32_t AArch64CA53ErratumStub::TEMPLATE[] = { 34 0x00000000, // Placeholder for erratum insn 35 0x00000000, // Palceholder for branch instruction 36 }; 37 38 AArch64CA53ErratumStub::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 49 AArch64CA53ErratumStub::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 62 AArch64CA53ErratumStub::~AArch64CA53ErratumStub() { 63 } 64 65 bool AArch64CA53ErratumStub::isMyDuty(const FragmentRef& pFragRef) const { 66 return false; 67 } 68 69 void 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 129 const std::string& AArch64CA53ErratumStub::name() const { 130 return m_Name; 131 } 132 133 const uint32_t* AArch64CA53ErratumStub::getData() const { 134 return m_pData; 135 } 136 137 const uint8_t* AArch64CA53ErratumStub::getContent() const { 138 return reinterpret_cast<const uint8_t*>(m_pData); 139 } 140 141 size_t AArch64CA53ErratumStub::size() const { 142 return m_Size; 143 } 144 145 size_t AArch64CA53ErratumStub::alignment() const { 146 return 8; 147 } 148 149 } // namespace mcld 150