Skip to content

Commit b1c26e7

Browse files
rafaelaulermemfrob
authored andcommitted
[BOLT-AArch64] Support rewriting bzip2
Summary: Add basic AArch64 read/write capability to be able to disassemble bzip2 for AArch64 compiled with gcc 5.4.0 and write it back after going through the basic BOLT pipeline with no block reordering (NOPs/unreachable blocks get removed). This is not for relocation mode. (cherry picked from FBD5701994)
1 parent a498be9 commit b1c26e7

File tree

5 files changed

+33
-29
lines changed

5 files changed

+33
-29
lines changed

bolt/BinaryFunction.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -775,13 +775,13 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
775775
Labels[0] = Ctx->createTempSymbol("BB0", false);
776776
addEntryPointAtOffset(0);
777777

778-
auto handleRIPOperand =
778+
auto handlePCRelOperand =
779779
[&](MCInst &Instruction, uint64_t Address, uint64_t Size) {
780780
uint64_t TargetAddress{0};
781781
MCSymbol *TargetSymbol{nullptr};
782782
if (!MIA->evaluateMemOperandTarget(Instruction, TargetAddress, Address,
783783
Size)) {
784-
errs() << "BOLT-ERROR: rip-relative operand can't be evaluated:\n";
784+
errs() << "BOLT-ERROR: PC-relative operand can't be evaluated:\n";
785785
BC.InstPrinter->printInst(&Instruction, errs(), "", *BC.STI);
786786
errs() << '\n';
787787
Instruction.dump_pretty(errs(), BC.InstPrinter.get());
@@ -790,7 +790,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
790790
}
791791
if (TargetAddress == 0) {
792792
if (opts::Verbosity >= 1) {
793-
outs() << "BOLT-INFO: rip-relative operand is zero in function "
793+
outs() << "BOLT-INFO: PC-relative operand is zero in function "
794794
<< *this << ".\n";
795795
}
796796
}
@@ -816,8 +816,11 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
816816
if (!TargetSymbol)
817817
TargetSymbol = BC.getOrCreateGlobalSymbol(TargetAddress, "DATAat");
818818
MIA->replaceMemOperandDisp(
819-
Instruction, MCOperand::createExpr(MCSymbolRefExpr::create(
820-
TargetSymbol, MCSymbolRefExpr::VK_None, *BC.Ctx)));
819+
Instruction, MCOperand::createExpr(BC.MIA->getTargetExprFor(
820+
Instruction,
821+
MCSymbolRefExpr::create(
822+
TargetSymbol, MCSymbolRefExpr::VK_None, *BC.Ctx),
823+
*BC.Ctx)));
821824
return true;
822825
};
823826

@@ -954,7 +957,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
954957
// Assign proper opcode for tail calls, so that they could be
955958
// treated as calls.
956959
if (!IsCall) {
957-
if (!MIA->convertJmpToTailCall(Instruction)) {
960+
if (!MIA->convertJmpToTailCall(Instruction, BC.Ctx.get())) {
958961
assert(IsCondBranch && "unknown tail call instruction");
959962
if (opts::Verbosity >= 2) {
960963
errs() << "BOLT-WARNING: conditional tail call detected in "
@@ -1007,12 +1010,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
10071010
// Add taken branch info.
10081011
TakenBranches.emplace_back(Offset, TargetAddress - getAddress());
10091012
}
1010-
Instruction.clear();
1011-
Instruction.addOperand(
1012-
MCOperand::createExpr(
1013-
MCSymbolRefExpr::create(TargetSymbol,
1014-
MCSymbolRefExpr::VK_None,
1015-
*Ctx)));
1013+
BC.MIA->replaceBranchTarget(Instruction, TargetSymbol, &*Ctx);
10161014

10171015
// Record call offset for profile matching.
10181016
if (IsCall) {
@@ -1036,7 +1034,8 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
10361034
llvm_unreachable("unexpected result");
10371035
case IndirectBranchType::POSSIBLE_TAIL_CALL:
10381036
{
1039-
auto Result = MIA->convertJmpToTailCall(Instruction);
1037+
auto Result =
1038+
MIA->convertJmpToTailCall(Instruction, BC.Ctx.get());
10401039
(void)Result;
10411040
assert(Result);
10421041
}
@@ -1053,8 +1052,8 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
10531052
};
10541053
}
10551054
// Indirect call. We only need to fix it if the operand is RIP-relative
1056-
if (IsSimple && MIA->hasRIPOperand(Instruction)) {
1057-
if (!handleRIPOperand(Instruction, AbsoluteInstrAddr, Size)) {
1055+
if (IsSimple && MIA->hasPCRelOperand(Instruction)) {
1056+
if (!handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size)) {
10581057
errs() << "BOLT-ERROR: cannot handle RIP operand at 0x"
10591058
<< Twine::utohexstr(AbsoluteInstrAddr)
10601059
<< ". Skipping function " << *this << ".\n";
@@ -1065,8 +1064,8 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
10651064
}
10661065
}
10671066
} else {
1068-
if (MIA->hasRIPOperand(Instruction)) {
1069-
if (!handleRIPOperand(Instruction, AbsoluteInstrAddr, Size)) {
1067+
if (MIA->hasPCRelOperand(Instruction)) {
1068+
if (!handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size)) {
10701069
errs() << "BOLT-ERROR: cannot handle RIP operand at 0x"
10711070
<< Twine::utohexstr(AbsoluteInstrAddr)
10721071
<< ". Skipping function " << *this << ".\n";
@@ -1152,7 +1151,7 @@ bool BinaryFunction::postProcessIndirectBranches() {
11521151
// If there's an indirect branch in a single-block function -
11531152
// it must be a tail call.
11541153
if (layout_size() == 1) {
1155-
BC.MIA->convertJmpToTailCall(Instr);
1154+
BC.MIA->convertJmpToTailCall(Instr, BC.Ctx.get());
11561155
return true;
11571156
}
11581157

@@ -1231,7 +1230,7 @@ bool BinaryFunction::postProcessIndirectBranches() {
12311230
}
12321231
return false;
12331232
}
1234-
BC.MIA->convertJmpToTailCall(Instr);
1233+
BC.MIA->convertJmpToTailCall(Instr, BC.Ctx.get());
12351234
}
12361235
}
12371236
return true;

bolt/Passes/BinaryPasses.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,12 +1005,12 @@ bool SimplifyRODataLoads::simplifyRODataLoads(
10051005
// Try to statically evaluate the target memory address;
10061006
uint64_t TargetAddress;
10071007

1008-
if (MIA->hasRIPOperand(Inst)) {
1009-
// Try to find the symbol that corresponds to the RIP-relative operand.
1008+
if (MIA->hasPCRelOperand(Inst)) {
1009+
// Try to find the symbol that corresponds to the PC-relative operand.
10101010
auto DispOpI = MIA->getMemOperandDisp(Inst);
1011-
assert(DispOpI != Inst.end() && "expected RIP-relative displacement");
1011+
assert(DispOpI != Inst.end() && "expected PC-relative displacement");
10121012
assert(DispOpI->isExpr() &&
1013-
"found RIP-relative with non-symbolic displacement");
1013+
"found PC-relative with non-symbolic displacement");
10141014

10151015
// Get displacement symbol.
10161016
const MCSymbolRefExpr *DisplExpr;

bolt/Passes/StokeInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void StokeInfo::checkInstr(const BinaryContext &BC, const BinaryFunction &BF,
6565
// check if this function modify stack or heap
6666
// TODO: more accurate analysis
6767
auto IsPush = BC.MIA->isPush(It);
68-
auto IsRipAddr = BC.MIA->hasRIPOperand(It);
68+
auto IsRipAddr = BC.MIA->hasPCRelOperand(It);
6969
if (IsPush) {
7070
FuncInfo.StackOut = true;
7171
}

bolt/RewriteInstance.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,10 @@ void RewriteInstance::aggregateData() {
675675

676676
void RewriteInstance::discoverStorage() {
677677

678-
EFMM.reset(new ExecutableFileMemoryManager());
678+
// Tell EE that we guarantee we don't need stubs for x86, but not for aarch64
679+
EFMM.reset(new ExecutableFileMemoryManager(
680+
/*AllowStubs*/ (BC->TheTriple->getArch() == llvm::Triple::aarch64 &&
681+
opts::Relocs)));
679682

680683
auto ELF64LEFile = dyn_cast<ELF64LEObjectFile>(InputFile);
681684
if (!ELF64LEFile) {
@@ -1224,7 +1227,8 @@ void RewriteInstance::discoverFileObjects() {
12241227
}
12251228

12261229
// Process PLT section.
1227-
disassemblePLT();
1230+
if (BC->TheTriple->getArch() == Triple::x86_64)
1231+
disassemblePLT();
12281232

12291233
// See if we missed any functions marked by FDE.
12301234
for (const auto &FDEI : CFIRdWrt->getFDEs()) {

bolt/RewriteInstance.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class ExecutableFileMemoryManager : public SectionMemoryManager {
104104
bool IsCode,
105105
bool IsReadOnly);
106106

107+
bool AllowStubs;
108+
107109
public:
108110
/// [start memory address] -> [segment info] mapping.
109111
std::map<uint64_t, SegmentInfo> SegmentMapInfo;
@@ -114,7 +116,7 @@ class ExecutableFileMemoryManager : public SectionMemoryManager {
114116
/// Information about non-allocatable sections.
115117
std::map<std::string, SectionInfo> NoteSectionInfo;
116118

117-
ExecutableFileMemoryManager() {}
119+
ExecutableFileMemoryManager(bool AllowStubs) : AllowStubs(AllowStubs) {}
118120

119121
~ExecutableFileMemoryManager();
120122

@@ -136,8 +138,7 @@ class ExecutableFileMemoryManager : public SectionMemoryManager {
136138
unsigned Alignment, unsigned SectionID,
137139
StringRef SectionName) override;
138140

139-
// Tell EE that we guarantee we don't need stubs.
140-
bool allowStubAllocation() const override { return false; }
141+
bool allowStubAllocation() const override { return AllowStubs; }
141142

142143
bool finalizeMemory(std::string *ErrMsg = nullptr) override;
143144
};

0 commit comments

Comments
 (0)