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