You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
4.7 KiB
150 lines
4.7 KiB
//===- AArch64CA53ErratumStub.cpp -----------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AArch64CA53ErratumStub.h"
|
|
#include "AArch64InsnHelpers.h"
|
|
#include "AArch64LDBackend.h"
|
|
#include "AArch64RelocationHelpers.h"
|
|
#include "AArch64Relocator.h"
|
|
|
|
#include "mcld/Fragment/FragmentRef.h"
|
|
#include "mcld/Fragment/Relocation.h"
|
|
#include "mcld/IRBuilder.h"
|
|
#include "mcld/LD/BranchIsland.h"
|
|
#include "mcld/LD/LDSymbol.h"
|
|
#include "mcld/LD/ResolveInfo.h"
|
|
|
|
#include <llvm/ADT/StringExtras.h>
|
|
#include <llvm/Support/ELF.h>
|
|
|
|
#include <cassert>
|
|
|
|
namespace mcld {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// AArch64CA53ErratumStub
|
|
//===----------------------------------------------------------------------===//
|
|
const uint32_t AArch64CA53ErratumStub::TEMPLATE[] = {
|
|
0x00000000, // Placeholder for erratum insn
|
|
0x00000000, // Palceholder for branch instruction
|
|
};
|
|
|
|
AArch64CA53ErratumStub::AArch64CA53ErratumStub()
|
|
: m_pData(NULL),
|
|
m_Name("erratum__prototype"),
|
|
m_Size(0x0) {
|
|
m_pData = TEMPLATE;
|
|
m_Size = sizeof(TEMPLATE);
|
|
addFixup(0x0, 0, AArch64Relocator::R_AARCH64_REWRITE_INSN);
|
|
addFixup(0x4, 0, llvm::ELF::R_AARCH64_JUMP26);
|
|
}
|
|
|
|
/// for doClone
|
|
AArch64CA53ErratumStub::AArch64CA53ErratumStub(const uint32_t* pData,
|
|
size_t pSize,
|
|
const char* pName,
|
|
const_fixup_iterator pBegin,
|
|
const_fixup_iterator pEnd)
|
|
: m_pData(pData),
|
|
m_Name(pName),
|
|
m_Size(pSize) {
|
|
for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it) {
|
|
addFixup(**it);
|
|
}
|
|
}
|
|
|
|
AArch64CA53ErratumStub::~AArch64CA53ErratumStub() {
|
|
}
|
|
|
|
bool AArch64CA53ErratumStub::isMyDuty(const FragmentRef& pFragRef) const {
|
|
return false;
|
|
}
|
|
|
|
void AArch64CA53ErratumStub::applyFixup(FragmentRef& pSrcFragRef,
|
|
IRBuilder& pBuilder,
|
|
BranchIsland& pIsland) {
|
|
assert(isMyDuty(pSrcFragRef));
|
|
|
|
// Build stub symbol name.
|
|
std::string sym_name("__");
|
|
sym_name.append(name())
|
|
.append(llvm::utohexstr(pIsland.numOfStubs()))
|
|
.append("@")
|
|
.append(pIsland.name());
|
|
|
|
// Create LDSymbol for the stub.
|
|
LDSymbol* stub_sym =
|
|
pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
|
|
sym_name,
|
|
ResolveInfo::NoType,
|
|
ResolveInfo::Define,
|
|
ResolveInfo::Local,
|
|
size(),
|
|
initSymValue(),
|
|
FragmentRef::Create(*this, initSymValue()),
|
|
ResolveInfo::Default);
|
|
setSymInfo(stub_sym->resolveInfo());
|
|
|
|
// Create the target symbol of the stub to the next instruction of erratum
|
|
// pattarn.
|
|
FragmentRef* target = FragmentRef::Create(*pSrcFragRef.frag(),
|
|
pSrcFragRef.offset() +
|
|
getErratumInsnOffset() +
|
|
AArch64InsnHelpers::InsnSize);
|
|
ResolveInfo* target_info = pBuilder.CreateLocalSymbol(*target);
|
|
|
|
// Apply the fixups.
|
|
fixup_iterator it = fixup_begin();
|
|
// Rewrite the first instruction as the erratum instruction.
|
|
Relocation* reloc =
|
|
Relocation::Create((*it)->type(),
|
|
*(FragmentRef::Create(*this, (*it)->offset())),
|
|
(*it)->addend());
|
|
reloc->setSymInfo(target_info);
|
|
|
|
std::unique_ptr<unsigned[]> code(new unsigned[getErratumSequenceSize() / 4]);
|
|
pSrcFragRef.memcpy(code.get(), getErratumSequenceSize(), 0);
|
|
reloc->target() =
|
|
code[getErratumInsnOffset() / AArch64InsnHelpers::InsnSize];
|
|
pIsland.addRelocation(*reloc);
|
|
|
|
// Construct the second instruction as a branch to target.
|
|
++it;
|
|
reloc = Relocation::Create((*it)->type(),
|
|
*(FragmentRef::Create(*this, (*it)->offset())),
|
|
(*it)->addend());
|
|
reloc->setSymInfo(target_info);
|
|
reloc->target() = AArch64InsnHelpers::buildBranchInsn();
|
|
pIsland.addRelocation(*reloc);
|
|
|
|
assert((++it) == fixup_end());
|
|
}
|
|
|
|
const std::string& AArch64CA53ErratumStub::name() const {
|
|
return m_Name;
|
|
}
|
|
|
|
const uint32_t* AArch64CA53ErratumStub::getData() const {
|
|
return m_pData;
|
|
}
|
|
|
|
const uint8_t* AArch64CA53ErratumStub::getContent() const {
|
|
return reinterpret_cast<const uint8_t*>(m_pData);
|
|
}
|
|
|
|
size_t AArch64CA53ErratumStub::size() const {
|
|
return m_Size;
|
|
}
|
|
|
|
size_t AArch64CA53ErratumStub::alignment() const {
|
|
return 8;
|
|
}
|
|
|
|
} // namespace mcld
|