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