• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AArch64CA53ErratumStub()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
AArch64CA53ErratumStub(const uint32_t * pData,size_t pSize,const char * pName,const_fixup_iterator pBegin,const_fixup_iterator pEnd)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 
~AArch64CA53ErratumStub()62 AArch64CA53ErratumStub::~AArch64CA53ErratumStub() {
63 }
64 
isMyDuty(const FragmentRef & pFragRef) const65 bool AArch64CA53ErratumStub::isMyDuty(const FragmentRef& pFragRef) const {
66   return false;
67 }
68 
applyFixup(FragmentRef & pSrcFragRef,IRBuilder & pBuilder,BranchIsland & pIsland)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 
name() const129 const std::string& AArch64CA53ErratumStub::name() const {
130   return m_Name;
131 }
132 
getData() const133 const uint32_t* AArch64CA53ErratumStub::getData() const {
134   return m_pData;
135 }
136 
getContent() const137 const uint8_t* AArch64CA53ErratumStub::getContent() const {
138   return reinterpret_cast<const uint8_t*>(m_pData);
139 }
140 
size() const141 size_t AArch64CA53ErratumStub::size() const {
142   return m_Size;
143 }
144 
alignment() const145 size_t AArch64CA53ErratumStub::alignment() const {
146   return 8;
147 }
148 
149 }  // namespace mcld
150