forked from OSchip/llvm-project
[ARM] add common parts for PACBTI-M support in the backend
This patch encapsulates decision logic about when and how to generate PAC/BTI related code. It's a part shared by PAC-RET, BTI placement, build attribute emission, etc, so it make sense committing it separately in order to unblock the aforementioned parts, which can proceed concurrently. This patch adds a few member functions to `ARMFunctionInfo`, which are currently unused, therefore there is no testing for them at the moment. This code is tested in follow-up PAC/BTI code gen patches. This patch is part of a series that adds support for the PACBTI-M extension of the Armv8.1-M architecture, as detailed here: https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension The PACBTI-M specification can be found in the Armv8-M Architecture Reference Manual: https://developer.arm.com/documentation/ddi0553/latest The following people contributed to this patch: - Momchil Velikov - Ties Stuij Reviewed By: danielkiss Differential Revision: https://reviews.llvm.org/D112423
This commit is contained in:
parent
ab2611d099
commit
c12c7a84b0
|
@ -13,8 +13,63 @@ using namespace llvm;
|
||||||
|
|
||||||
void ARMFunctionInfo::anchor() {}
|
void ARMFunctionInfo::anchor() {}
|
||||||
|
|
||||||
|
static bool GetBranchTargetEnforcement(MachineFunction &MF) {
|
||||||
|
const auto &Subtarget = MF.getSubtarget<ARMSubtarget>();
|
||||||
|
if (!Subtarget.isMClass() || !Subtarget.hasV7Ops())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const Function &F = MF.getFunction();
|
||||||
|
if (!F.hasFnAttribute("branch-target-enforcement")) {
|
||||||
|
if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
|
||||||
|
F.getParent()->getModuleFlag("branch-target-enforcement")))
|
||||||
|
return BTE->getZExtValue();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StringRef BTIEnable =
|
||||||
|
F.getFnAttribute("branch-target-enforcement").getValueAsString();
|
||||||
|
assert(BTIEnable.equals_insensitive("true") ||
|
||||||
|
BTIEnable.equals_insensitive("false"));
|
||||||
|
return BTIEnable.equals_insensitive("true");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pair returns values for the ARMFunctionInfo members
|
||||||
|
// SignReturnAddress and SignReturnAddressAll respectively.
|
||||||
|
static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
|
||||||
|
if (!F.hasFnAttribute("sign-return-address")) {
|
||||||
|
const Module &M = *F.getParent();
|
||||||
|
if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
|
||||||
|
M.getModuleFlag("sign-return-address"))) {
|
||||||
|
if (Sign->getZExtValue()) {
|
||||||
|
if (const auto *All = mdconst::extract_or_null<ConstantInt>(
|
||||||
|
M.getModuleFlag("sign-return-address-all")))
|
||||||
|
return {true, All->getZExtValue()};
|
||||||
|
return {true, false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {false, false};
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
|
||||||
|
if (Scope.equals("none"))
|
||||||
|
return {false, false};
|
||||||
|
|
||||||
|
if (Scope.equals("all"))
|
||||||
|
return {true, true};
|
||||||
|
|
||||||
|
assert(Scope.equals("non-leaf"));
|
||||||
|
return {true, false};
|
||||||
|
}
|
||||||
|
|
||||||
ARMFunctionInfo::ARMFunctionInfo(MachineFunction &MF)
|
ARMFunctionInfo::ARMFunctionInfo(MachineFunction &MF)
|
||||||
: isThumb(MF.getSubtarget<ARMSubtarget>().isThumb()),
|
: isThumb(MF.getSubtarget<ARMSubtarget>().isThumb()),
|
||||||
hasThumb2(MF.getSubtarget<ARMSubtarget>().hasThumb2()),
|
hasThumb2(MF.getSubtarget<ARMSubtarget>().hasThumb2()),
|
||||||
IsCmseNSEntry(MF.getFunction().hasFnAttribute("cmse_nonsecure_entry")),
|
IsCmseNSEntry(MF.getFunction().hasFnAttribute("cmse_nonsecure_entry")),
|
||||||
IsCmseNSCall(MF.getFunction().hasFnAttribute("cmse_nonsecure_call")) {}
|
IsCmseNSCall(MF.getFunction().hasFnAttribute("cmse_nonsecure_call")),
|
||||||
|
BranchTargetEnforcement(GetBranchTargetEnforcement(MF)) {
|
||||||
|
|
||||||
|
const auto &Subtarget = MF.getSubtarget<ARMSubtarget>();
|
||||||
|
if (Subtarget.isMClass() && Subtarget.hasV7Ops())
|
||||||
|
std::tie(SignReturnAddress, SignReturnAddressAll) =
|
||||||
|
GetSignReturnAddress(MF.getFunction());
|
||||||
|
}
|
||||||
|
|
|
@ -142,6 +142,17 @@ class ARMFunctionInfo : public MachineFunctionInfo {
|
||||||
/// con/destructors).
|
/// con/destructors).
|
||||||
bool PreservesR0 = false;
|
bool PreservesR0 = false;
|
||||||
|
|
||||||
|
/// True if the function should sign its return address.
|
||||||
|
bool SignReturnAddress = false;
|
||||||
|
|
||||||
|
/// True if the fucntion should sign its return address, even if LR is not
|
||||||
|
/// saved.
|
||||||
|
bool SignReturnAddressAll = false;
|
||||||
|
|
||||||
|
/// True if BTI instructions should be placed at potential indirect jump
|
||||||
|
/// destinations.
|
||||||
|
bool BranchTargetEnforcement = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ARMFunctionInfo() = default;
|
ARMFunctionInfo() = default;
|
||||||
|
|
||||||
|
@ -268,6 +279,20 @@ public:
|
||||||
|
|
||||||
void setPreservesR0() { PreservesR0 = true; }
|
void setPreservesR0() { PreservesR0 = true; }
|
||||||
bool getPreservesR0() const { return PreservesR0; }
|
bool getPreservesR0() const { return PreservesR0; }
|
||||||
|
|
||||||
|
bool shouldSignReturnAddress() const {
|
||||||
|
return shouldSignReturnAddress(LRSpilled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldSignReturnAddress(bool SpillsLR) const {
|
||||||
|
if (!SignReturnAddress)
|
||||||
|
return false;
|
||||||
|
if (SignReturnAddressAll)
|
||||||
|
return true;
|
||||||
|
return LRSpilled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
Loading…
Reference in New Issue