-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[BOLT][AArch64] Support for pointer authentication #117578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
61efea9
0353abb
6217b66
d5fae5e
6b7957a
e0c0957
15d008f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
|
||
#include "bolt/Core/MCPlus.h" | ||
#include "bolt/Core/Relocation.h" | ||
#include "bolt/Utils/CommandLineOpts.h" | ||
#include "llvm/ADT/ArrayRef.h" | ||
#include "llvm/ADT/BitVector.h" | ||
#include "llvm/ADT/StringMap.h" | ||
|
@@ -27,6 +28,7 @@ | |
#include "llvm/MC/MCInstrAnalysis.h" | ||
#include "llvm/MC/MCInstrDesc.h" | ||
#include "llvm/MC/MCInstrInfo.h" | ||
#include "llvm/MC/MCSymbol.h" | ||
#include "llvm/Support/Allocator.h" | ||
#include "llvm/Support/Casting.h" | ||
#include "llvm/Support/ErrorHandling.h" | ||
|
@@ -546,6 +548,27 @@ class MCPlusBuilder { | |
return Analysis->isCall(Inst) || isTailCall(Inst); | ||
} | ||
|
||
virtual std::optional<StringRef> getCalleeName(const MCInst &Inst) const { | ||
assert(isCall(Inst)); | ||
if (MCPlus::getNumPrimeOperands(Inst) != 1 || !Inst.getOperand(0).isExpr()) | ||
return {}; | ||
|
||
const MCSymbol *CalleeSymbol = getTargetSymbol(Inst); | ||
assert(CalleeSymbol != nullptr); | ||
return CalleeSymbol->getName(); | ||
} | ||
|
||
virtual bool isNoReturnCall(const MCInst &Inst) const { | ||
if (!isCall(Inst)) | ||
return false; | ||
auto calleeName = getCalleeName(Inst); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: start with uppercase |
||
if (calleeName) | ||
for (std::string &Name : opts::AssumeNoReturnFunctions) | ||
if (calleeName->equals(Name)) | ||
return true; | ||
return false; | ||
} | ||
|
||
virtual bool isReturn(const MCInst &Inst) const { | ||
return Analysis->isReturn(Inst); | ||
} | ||
|
@@ -648,6 +671,13 @@ class MCPlusBuilder { | |
llvm_unreachable("not implemented"); | ||
return false; | ||
} | ||
virtual bool isPAuth(MCInst &Inst) const { | ||
llvm_unreachable("not implemented"); | ||
} | ||
|
||
virtual bool isPSign(MCInst &Inst) const { | ||
llvm_unreachable("not implemented"); | ||
} | ||
|
||
virtual bool isCleanRegXOR(const MCInst &Inst) const { | ||
llvm_unreachable("not implemented"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef BOLT_PASSES_INSERT_NEGATE_RA_STATE_PASS | ||
bgergely0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#define BOLT_PASSES_INSERT_NEGATE_RA_STATE_PASS | ||
|
||
#include "bolt/Passes/BinaryPasses.h" | ||
#include <stack> | ||
|
||
namespace llvm { | ||
namespace bolt { | ||
|
||
class InsertNegateRAState : public BinaryFunctionPass { | ||
public: | ||
explicit InsertNegateRAState() : BinaryFunctionPass(false) {} | ||
|
||
const char *getName() const override { return "insert-negate-ra-state-pass"; } | ||
|
||
/// Pass entry point | ||
Error runOnFunctions(BinaryContext &BC) override; | ||
void runOnFunction(BinaryFunction &BF); | ||
bool addNegateRAStateAfterPacOrAuth(BinaryFunction &BF); | ||
bool BBhasAUTH(BinaryContext &BC, BinaryBasicBlock *BB); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use lower-camelcase for some relevant functions below? Consider making them private if they are not used outiside this pass. Also it'll be great if you can provide some short description to some of these, |
||
bool BBhasSIGN(BinaryContext &BC, BinaryBasicBlock *BB); | ||
void explore_call_graph(BinaryContext &BC, BinaryBasicBlock *BB); | ||
void process_signed_BB(BinaryContext &BC, BinaryBasicBlock *BB, | ||
std::stack<BinaryBasicBlock *> *SignedStack, | ||
std::stack<BinaryBasicBlock *> *UnsignedStack); | ||
void process_unsigned_BB(BinaryContext &BC, BinaryBasicBlock *BB, | ||
std::stack<BinaryBasicBlock *> *SignedStack, | ||
std::stack<BinaryBasicBlock *> *UnsignedStack); | ||
}; | ||
|
||
} // namespace bolt | ||
} // namespace llvm | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -201,7 +201,11 @@ int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const { | |
InstrSeen = (&Inst == Instr); | ||
continue; | ||
} | ||
if (Function->getBinaryContext().MIB->isCFI(Inst)) { | ||
// Fix: ignoring OpNegateRAState CFIs here, as they dont have a "State" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this handled later on? Can you reword your comment to something like
|
||
// number associated with them. | ||
if (Function->getBinaryContext().MIB->isCFI(Inst) && | ||
(Function->getCFIFor(Inst)->getOperation() != | ||
MCCFIInstruction::OpNegateRAState)) { | ||
LastCFI = &Inst; | ||
break; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2155,7 +2155,8 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { | |
addCFIPlaceholders(Offset, InsertBB); | ||
} | ||
|
||
const bool IsBlockEnd = MIB->isTerminator(Instr); | ||
const bool IsBlockEnd = | ||
MIB->isTerminator(Instr) || MIB->isNoReturnCall(Instr); | ||
IsLastInstrNop = MIB->isNoop(Instr); | ||
if (!IsLastInstrNop) | ||
LastInstrOffset = Offset; | ||
|
@@ -2242,8 +2243,11 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { | |
// | ||
// Conditional tail call is a special case since we don't add a taken | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adapting this earlier comment to mention this new special case? |
||
// branch successor for it. | ||
IsPrevFT = !MIB->isTerminator(*LastInstr) || | ||
MIB->getConditionalTailCall(*LastInstr); | ||
if (MIB->isNoReturnCall(*LastInstr)) | ||
IsPrevFT = false; | ||
else | ||
IsPrevFT = !MIB->isTerminator(*LastInstr) || | ||
MIB->getConditionalTailCall(*LastInstr); | ||
} else if (BB->succ_size() == 1) { | ||
IsPrevFT = MIB->isConditionalBranch(*LastInstr); | ||
} else { | ||
|
@@ -2596,6 +2600,7 @@ struct CFISnapshot { | |
void advanceTo(int32_t State) { | ||
for (int32_t I = CurState, E = State; I != E; ++I) { | ||
const MCCFIInstruction &Instr = FDE[I]; | ||
assert(Instr.getOperation() != MCCFIInstruction::OpNegateRAState); | ||
if (Instr.getOperation() != MCCFIInstruction::OpRestoreState) { | ||
update(Instr, I); | ||
continue; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -632,8 +632,10 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { | |
// DW_CFA_GNU_window_save and DW_CFA_GNU_NegateRAState just use the same | ||
// id but mean different things. The latter is used in AArch64. | ||
if (Function.getBinaryContext().isAArch64()) { | ||
Function.addCFIInstruction( | ||
Offset, MCCFIInstruction::createNegateRAState(nullptr)); | ||
// Fix: not adding OpNegateRAState since the location they are needed | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can modify/expand the earlier comment (line 632) to explain this one, dropping the word 'Fix'. |
||
// depends on the order of BasicBlocks, which changes during | ||
// optimizations. They are generated in InsertNegateRAStatePass after | ||
// optimizations instead. | ||
break; | ||
} | ||
if (opts::Verbosity >= 1) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could move implementation to the cpp file (of
getCalleeName
andisNoReturnCall
) if we want to avoid including more headers earlier in this file.