Home | History | Annotate | Download | only in AArch64
      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