Support the min of module flags when linking, use for AArch64 BTI/PAC-RET

LTO objects might compiled with different `mbranch-protection` flags which will cause an error in the linker.
Such a setup is allowed in the normal build with this change that is possible.

Reviewed By: pcc

Differential Revision: https://reviews.llvm.org/D123493
This commit is contained in:
Daniel Kiss 2022-04-13 09:31:25 +02:00
parent e500062493
commit b0343a38a5
56 changed files with 289 additions and 155 deletions

View File

@ -729,7 +729,10 @@ void CodeGenModule::Release() {
// attributes, but we use module metadata to emit build attributes. This is
// needed for LTO, where the function attributes are inside bitcode
// serialised into a global variable by the time build attributes are
// emitted, so we can't access them.
// emitted, so we can't access them. LTO objects could be compiled with
// different flags therefore module flags are set to "Min" behavior to achieve
// the same end result of the normal build where e.g BTI is off if any object
// doesn't support it.
if (Context.getTargetInfo().hasFeature("ptrauth") &&
LangOpts.getSignReturnAddressScope() !=
LangOptions::SignReturnAddressScopeKind::None)
@ -743,16 +746,16 @@ void CodeGenModule::Release() {
Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
Arch == llvm::Triple::aarch64_be) {
getModule().addModuleFlag(llvm::Module::Error, "branch-target-enforcement",
getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement",
LangOpts.BranchTargetEnforcement);
getModule().addModuleFlag(llvm::Module::Error, "sign-return-address",
getModule().addModuleFlag(llvm::Module::Min, "sign-return-address",
LangOpts.hasSignReturnAddress());
getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all",
getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all",
LangOpts.isSignReturnAddressScopeAll());
getModule().addModuleFlag(llvm::Module::Error,
getModule().addModuleFlag(llvm::Module::Min,
"sign-return-address-with-bkey",
!LangOpts.isSignReturnAddressWithAKey());
}

View File

@ -19,28 +19,28 @@
// Check module attributes
// NONE: !{i32 1, !"branch-target-enforcement", i32 0}
// ALL: !{i32 1, !"branch-target-enforcement", i32 0}
// PART: !{i32 1, !"branch-target-enforcement", i32 0}
// BTE: !{i32 1, !"branch-target-enforcement", i32 1}
// B-KEY: !{i32 1, !"branch-target-enforcement", i32 0}
// NONE: !{i32 8, !"branch-target-enforcement", i32 0}
// ALL: !{i32 8, !"branch-target-enforcement", i32 0}
// PART: !{i32 8, !"branch-target-enforcement", i32 0}
// BTE: !{i32 8, !"branch-target-enforcement", i32 1}
// B-KEY: !{i32 8, !"branch-target-enforcement", i32 0}
// NONE: !{i32 1, !"sign-return-address", i32 0}
// ALL: !{i32 1, !"sign-return-address", i32 1}
// PART: !{i32 1, !"sign-return-address", i32 1}
// BTE: !{i32 1, !"sign-return-address", i32 0}
// B-KEY: !{i32 1, !"sign-return-address", i32 1}
// NONE: !{i32 8, !"sign-return-address", i32 0}
// ALL: !{i32 8, !"sign-return-address", i32 1}
// PART: !{i32 8, !"sign-return-address", i32 1}
// BTE: !{i32 8, !"sign-return-address", i32 0}
// B-KEY: !{i32 8, !"sign-return-address", i32 1}
// NONE: !{i32 1, !"sign-return-address-all", i32 0}
// ALL: !{i32 1, !"sign-return-address-all", i32 1}
// PART: !{i32 1, !"sign-return-address-all", i32 0}
// BTE: !{i32 1, !"sign-return-address-all", i32 0}
// B-KEY: !{i32 1, !"sign-return-address-all", i32 0}
// NONE: !{i32 8, !"sign-return-address-all", i32 0}
// ALL: !{i32 8, !"sign-return-address-all", i32 1}
// PART: !{i32 8, !"sign-return-address-all", i32 0}
// BTE: !{i32 8, !"sign-return-address-all", i32 0}
// B-KEY: !{i32 8, !"sign-return-address-all", i32 0}
// NONE: !{i32 1, !"sign-return-address-with-bkey", i32 0}
// ALL: !{i32 1, !"sign-return-address-with-bkey", i32 0}
// PART: !{i32 1, !"sign-return-address-with-bkey", i32 0}
// BTE: !{i32 1, !"sign-return-address-with-bkey", i32 0}
// B-KEY: !{i32 1, !"sign-return-address-with-bkey", i32 1}
// NONE: !{i32 8, !"sign-return-address-with-bkey", i32 0}
// ALL: !{i32 8, !"sign-return-address-with-bkey", i32 0}
// PART: !{i32 8, !"sign-return-address-with-bkey", i32 0}
// BTE: !{i32 8, !"sign-return-address-with-bkey", i32 0}
// B-KEY: !{i32 8, !"sign-return-address-with-bkey", i32 1}
void foo() {}

View File

@ -15,19 +15,19 @@
// Check module attributes
// NONE: !{i32 1, !"branch-target-enforcement", i32 0}
// PART: !{i32 1, !"branch-target-enforcement", i32 0}
// ALL: !{i32 1, !"branch-target-enforcement", i32 0}
// BTE: !{i32 1, !"branch-target-enforcement", i32 1}
// NONE: !{i32 8, !"branch-target-enforcement", i32 0}
// PART: !{i32 8, !"branch-target-enforcement", i32 0}
// ALL: !{i32 8, !"branch-target-enforcement", i32 0}
// BTE: !{i32 8, !"branch-target-enforcement", i32 1}
// NONE: !{i32 1, !"sign-return-address", i32 0}
// PART: !{i32 1, !"sign-return-address", i32 1}
// ALL: !{i32 1, !"sign-return-address", i32 1}
// BTE: !{i32 1, !"sign-return-address", i32 0}
// NONE: !{i32 8, !"sign-return-address", i32 0}
// PART: !{i32 8, !"sign-return-address", i32 1}
// ALL: !{i32 8, !"sign-return-address", i32 1}
// BTE: !{i32 8, !"sign-return-address", i32 0}
// NONE: !{i32 1, !"sign-return-address-all", i32 0}
// PART: !{i32 1, !"sign-return-address-all", i32 0}
// ALL: !{i32 1, !"sign-return-address-all", i32 1}
// BTE: !{i32 1, !"sign-return-address-all", i32 0}
// NONE: !{i32 8, !"sign-return-address-all", i32 0}
// PART: !{i32 8, !"sign-return-address-all", i32 0}
// ALL: !{i32 8, !"sign-return-address-all", i32 1}
// BTE: !{i32 8, !"sign-return-address-all", i32 0}
void foo() {}

View File

@ -15,4 +15,4 @@ __attribute__((target("arch=cortex-m0"))) void f() {}
// CHECK-NOT: attributes { {{.*}} "branch-target-enforcement"
/// Check that there are branch protection module attributes despite the warning.
// CHECK: !{i32 1, !"branch-target-enforcement", i32 1}
// CHECK: !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -146,9 +146,12 @@ public:
/// Takes the max of the two values, which are required to be integers.
Max = 7,
/// Takes the min of the two values, which are required to be integers.
Min = 8,
// Markers:
ModFlagBehaviorFirstVal = Error,
ModFlagBehaviorLastVal = Max
ModFlagBehaviorLastVal = Min
};
/// Checks if Metadata represents a valid ModFlagBehavior, and stores the

View File

@ -4388,6 +4388,24 @@ bool llvm::UpgradeModuleFlags(Module &M) {
}
}
}
// Upgrade branch protection and return address signing module flags. The
// module flag behavior for these fields were Error and now they are Min.
if (ID->getString() == "branch-target-enforcement" ||
ID->getString().startswith("sign-return-address")) {
if (auto *Behavior =
mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
if (Behavior->getLimitedValue() == Module::Error) {
Type *Int32Ty = Type::getInt32Ty(M.getContext());
Metadata *Ops[3] = {
ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Module::Min)),
Op->getOperand(1), Op->getOperand(2)};
ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
Changed = true;
}
}
}
// Upgrade Objective-C Image Info Section. Removed the whitespce in the
// section name so that llvm-lto will not complain about mismatching
// module flags that is functionally the same.

View File

@ -1623,6 +1623,13 @@ Verifier::visitModuleFlag(const MDNode *Op,
// These behavior types accept any value.
break;
case Module::Min: {
Check(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),
"invalid value for 'min' module flag (expected constant integer)",
Op->getOperand(2));
break;
}
case Module::Max: {
Check(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),
"invalid value for 'max' module flag (expected constant integer)",

View File

@ -12,6 +12,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DiagnosticPrinter.h"
@ -1256,6 +1257,9 @@ Error IRLinker::linkModuleFlagsMetadata() {
if (!SrcModFlags)
return Error::success();
// Check for module flag for updates before do anything.
UpgradeModuleFlags(*SrcM);
// If the destination module doesn't have module flags yet, then just copy
// over the source module's flags.
NamedMDNode *DstModFlags = DstM.getOrInsertModuleFlagsMetadata();
@ -1338,11 +1342,15 @@ Error IRLinker::linkModuleFlagsMetadata() {
// Diagnose inconsistent merge behavior types.
if (SrcBehaviorValue != DstBehaviorValue) {
bool MinAndWarn = (SrcBehaviorValue == Module::Min &&
DstBehaviorValue == Module::Warning) ||
(DstBehaviorValue == Module::Min &&
SrcBehaviorValue == Module::Warning);
bool MaxAndWarn = (SrcBehaviorValue == Module::Max &&
DstBehaviorValue == Module::Warning) ||
(DstBehaviorValue == Module::Max &&
SrcBehaviorValue == Module::Warning);
if (!MaxAndWarn)
if (!(MaxAndWarn || MinAndWarn))
return stringErr("linking module flags '" + ID->getString() +
"': IDs have conflicting behaviors in '" +
SrcM->getModuleIdentifier() + "' and '" +
@ -1371,6 +1379,25 @@ Error IRLinker::linkModuleFlagsMetadata() {
emitWarning(Str);
}
// Choose the minimum if either source or destination request Min behavior.
if (DstBehaviorValue == Module::Min || SrcBehaviorValue == Module::Min) {
ConstantInt *DstValue =
mdconst::extract<ConstantInt>(DstOp->getOperand(2));
ConstantInt *SrcValue =
mdconst::extract<ConstantInt>(SrcOp->getOperand(2));
// The resulting flag should have a Min behavior, and contain the minimum
// value from between the source and destination values.
Metadata *FlagOps[] = {
(DstBehaviorValue != Module::Min ? SrcOp : DstOp)->getOperand(0), ID,
(SrcValue->getZExtValue() < DstValue->getZExtValue() ? SrcOp : DstOp)
->getOperand(2)};
MDNode *Flag = MDNode::get(DstM.getContext(), FlagOps);
DstModFlags->setOperand(DstIndex, Flag);
Flags[ID].first = Flag;
continue;
}
// Choose the maximum if either source or destination request Max behavior.
if (DstBehaviorValue == Module::Max || SrcBehaviorValue == Module::Max) {
ConstantInt *DstValue =

View File

@ -0,0 +1,16 @@
;; Test that module flags "branch-target-enforcement" and "sign-return-address" can be upgraded to
;; are upgraded from Error to Min.
; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 1}
!3 = !{i32 1, !"sign-return-address-with-bkey", i32 1}
;CHECK: !0 = !{i32 8, !"branch-target-enforcement", i32 1}
;CHECK: !1 = !{i32 8, !"sign-return-address", i32 1}
;CHECK: !2 = !{i32 8, !"sign-return-address-all", i32 1}
;CHECK: !3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}

View File

@ -89,10 +89,10 @@
!3 = !{i32 7, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{i32 1, !"branch-target-enforcement", i32 0}
!7 = !{i32 1, !"sign-return-address", i32 0}
!8 = !{i32 1, !"sign-return-address-all", i32 0}
!9 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!6 = !{i32 8, !"branch-target-enforcement", i32 0}
!7 = !{i32 8, !"sign-return-address", i32 0}
!8 = !{i32 8, !"sign-return-address-all", i32 0}
!9 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!10 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git b19275ba870a06c5ef0428af6264ffd28c7cde9e)"}
!11 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
!12 = !DISubroutineType(types: !13)

View File

@ -69,10 +69,10 @@
!3 = !{i32 7, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{i32 1, !"branch-target-enforcement", i32 0}
!7 = !{i32 1, !"sign-return-address", i32 0}
!8 = !{i32 1, !"sign-return-address-all", i32 0}
!9 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!6 = !{i32 8, !"branch-target-enforcement", i32 0}
!7 = !{i32 8, !"sign-return-address", i32 0}
!8 = !{i32 8, !"sign-return-address-all", i32 0}
!9 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!10 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git b19275ba870a06c5ef0428af6264ffd28c7cde9e)"}
!11 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 6, type: !12, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !26)
!12 = !DISubroutineType(types: !13)

View File

@ -328,10 +328,10 @@ attributes #4 = { nounwind }
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 12, i32 0]}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = !{i32 1, !"wchar_size", i32 4}
!3 = !{i32 1, !"branch-target-enforcement", i32 0}
!4 = !{i32 1, !"sign-return-address", i32 0}
!5 = !{i32 1, !"sign-return-address-all", i32 0}
!6 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!3 = !{i32 8, !"branch-target-enforcement", i32 0}
!4 = !{i32 8, !"sign-return-address", i32 0}
!5 = !{i32 8, !"sign-return-address-all", i32 0}
!6 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!7 = !{i32 7, !"PIC Level", i32 2}
!8 = !{i32 7, !"uwtable", i32 1}
!9 = !{i32 7, !"frame-pointer", i32 1}

View File

@ -8,10 +8,10 @@ attributes #0 = { "branch-target-enforcement"="true" }
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!3 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
; Both attributes present in a file with no functions.
; ASM: .word 3221225472

View File

@ -10,10 +10,10 @@ entry:
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 0}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!3 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 0}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
; BTI attribute present
; ASM: .word 3221225472

View File

@ -10,10 +10,10 @@ entry:
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!3 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
; PAC attribute present
; ASM: .word 3221225472

View File

@ -10,10 +10,10 @@ entry:
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!3 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
; Both attribute present
; ASM: .word 3221225472

View File

@ -17,10 +17,10 @@ attributes #1 = { "branch-target-enforcement"="true" }
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 0}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!3 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 0}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
; Note is not emited if module has no properties
; ASM-NOT: .note.gnu.property

View File

@ -65,7 +65,7 @@ attributes #2 = { nofree noinline norecurse nounwind writeonly }
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 1, !"branch-target-enforcement", i32 0}
!3 = !{i32 1, !"sign-return-address", i32 1}
!4 = !{i32 1, !"sign-return-address-all", i32 1}
!5 = !{i32 1, !"sign-return-address-with-bkey", i32 1}
!2 = !{i32 8, !"branch-target-enforcement", i32 0}
!3 = !{i32 8, !"sign-return-address", i32 1}
!4 = !{i32 8, !"sign-return-address-all", i32 1}
!5 = !{i32 8, !"sign-return-address-with-bkey", i32 1}

View File

@ -71,7 +71,7 @@ attributes #5 = { nounwind }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"branch-target-enforcement", i32 1}
!2 = !{i32 1, !"sign-return-address", i32 1}
!3 = !{i32 1, !"sign-return-address-all", i32 0}
!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!1 = !{i32 8, !"branch-target-enforcement", i32 1}
!2 = !{i32 8, !"sign-return-address", i32 1}
!3 = !{i32 8, !"sign-return-address-all", i32 0}
!4 = !{i32 8, !"sign-return-address-with-bkey", i32 0}

View File

@ -48,4 +48,4 @@ declare void @notsetjmp()
attributes #0 = { returns_twice }
; !llvm.module.flags = !{!0}
; !0 = !{i32 1, !"branch-target-enforcement", i32 1}
; !0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -80,4 +80,4 @@ attributes #0 = { returns_twice }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -52,4 +52,4 @@ declare void @notsetjmp()
attributes #0 = { returns_twice }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -16,6 +16,6 @@ entry:
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -47,4 +47,4 @@ attributes #0 = { returns_twice }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -89,4 +89,4 @@ attributes #0 = { returns_twice }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -93,9 +93,9 @@
!6 = !{i32 1, !"static_rwdata", i32 1}
!7 = !{i32 1, !"enumsize_buildattr", i32 2}
!8 = !{i32 1, !"armlib_unavailable", i32 0}
!9 = !{i32 1, !"branch-target-enforcement", i32 0}
!10 = !{i32 1, !"sign-return-address", i32 0}
!11 = !{i32 1, !"sign-return-address-all", i32 0}
!9 = !{i32 8, !"branch-target-enforcement", i32 0}
!10 = !{i32 8, !"sign-return-address", i32 0}
!11 = !{i32 8, !"sign-return-address-all", i32 0}
!12 = !{!"Component: ARM Compiler 6.17.0.0 (permissive) Tool: armclang [00000000]"}
!13 = distinct !DISubprogram(name: "arm_max_no_idx_f32", scope: !1, file: !1, line: 5, type: !14, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !23)
!14 = !DISubroutineType(types: !15)

View File

@ -126,7 +126,7 @@
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
...
---

View File

@ -43,7 +43,7 @@
}
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
...
---

View File

@ -19,4 +19,4 @@ entry:
}
!llvm.module.flags = !{!1}
!1 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -132,4 +132,4 @@ return:
}
!llvm.module.flags = !{!1}
!1 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -28,7 +28,7 @@
}
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
...
---

View File

@ -133,4 +133,4 @@ attributes #2 = { minsize nofree norecurse nounwind optsize "branch-target-enfor
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}

View File

@ -79,4 +79,4 @@ attributes #2 = { minsize nofree norecurse nounwind optsize "branch-target-enfor
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -64,4 +64,4 @@ attributes #0 = { minsize nofree norecurse nounwind optsize }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}

View File

@ -48,4 +48,4 @@ attributes #0 = { minsize nofree norecurse nounwind optsize }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}

View File

@ -15,9 +15,9 @@
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
...
---

View File

@ -14,9 +14,9 @@ entry:
declare dso_local i32 @_Z1gi(i32)
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; Check the function starts with `pacbti` and correct unwind info is emitted
; CHECK-LABEL: _Z1fi:

View File

@ -97,9 +97,9 @@ attributes #1 = { "cmse_nonsecure_entry" "target-features"="+8msecext,+armv8-m.m
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; UNWIND-LABEL: FunctionAddress: 0x0
; UNWIND: 0x00 ; vsp = vsp + 4

View File

@ -32,6 +32,6 @@ attributes #0 = { nounwind }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -120,9 +120,9 @@ attributes #0 = { minsize nofree norecurse nounwind optsize uwtable}
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; UNWIND-LABEL: FunctionAddress: 0x0
; UNWIND: 0xB4 ; pop ra_auth_code

View File

@ -84,6 +84,6 @@ attributes #0 = { minsize nofree norecurse nounwind optsize}
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -138,9 +138,9 @@ attributes #0 = { minsize noinline norecurse nounwind optsize readnone uwtable }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; UNWIND-LABEL: FunctionAddress: 0x4

View File

@ -172,9 +172,9 @@ attributes #2 = { noreturn }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; UNWIND-LABEL: FunctionAddress: 0x0

View File

@ -93,6 +93,6 @@ attributes #1 = { minsize nofree norecurse nounwind optsize "sign-return-address
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -60,9 +60,9 @@ declare dso_local i32 @_Z1giPi(i32, i32*) local_unnamed_addr
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; UNWIND-LABEL: FunctionAddress: 0x0
; UNWIND: 0x97 ; vsp = r7

View File

@ -26,6 +26,6 @@ attributes #0 = { noinline nounwind }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 1}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -72,6 +72,6 @@ attributes #1 = { nounwind }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -90,9 +90,9 @@ attributes #1 = { nounwind }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
; UNWIND-LABEL: FunctionAddress
; UNWIND: 0x01 ; vsp = vsp + 8

View File

@ -120,6 +120,6 @@ attributes #0 = { nounwind }
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 1, !"branch-target-enforcement", i32 0}
!1 = !{i32 1, !"sign-return-address", i32 1}
!2 = !{i32 1, !"sign-return-address-all", i32 0}
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}

View File

@ -46,10 +46,10 @@ define void @f4() !dbg !19 {
!7 = !{i32 7, !"Dwarf Version", i32 4}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{i32 1, !"wchar_size", i32 4}
!10 = !{i32 1, !"branch-target-enforcement", i32 0}
!11 = !{i32 1, !"sign-return-address", i32 0}
!12 = !{i32 1, !"sign-return-address-all", i32 0}
!13 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!10 = !{i32 8, !"branch-target-enforcement", i32 0}
!11 = !{i32 8, !"sign-return-address", i32 0}
!12 = !{i32 8, !"sign-return-address-all", i32 0}
!13 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!14 = !{i32 7, !"PIC Level", i32 2}
!15 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !16, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
!16 = !DISubroutineType(types: !17)

View File

@ -20,10 +20,10 @@ declare void @llvm.instrprof.cover(i8*, i64, i32, i32)
!2 = !{i32 7, !"Dwarf Version", i32 4}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 1, !"branch-target-enforcement", i32 0}
!6 = !{i32 1, !"sign-return-address", i32 0}
!7 = !{i32 1, !"sign-return-address-all", i32 0}
!8 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 8, !"branch-target-enforcement", i32 0}
!6 = !{i32 8, !"sign-return-address", i32 0}
!7 = !{i32 8, !"sign-return-address-all", i32 0}
!8 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!9 = !{i32 7, !"uwtable", i32 1}
!10 = !{i32 7, !"frame-pointer", i32 1}
!11 = !{!"clang version 14.0.0"}

View File

@ -34,10 +34,10 @@ declare void @llvm.instrprof.increment(i8*, i64, i32, i32)
!2 = !{i32 7, !"Dwarf Version", i32 4}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 1, !"branch-target-enforcement", i32 0}
!6 = !{i32 1, !"sign-return-address", i32 0}
!7 = !{i32 1, !"sign-return-address-all", i32 0}
!8 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 8, !"branch-target-enforcement", i32 0}
!6 = !{i32 8, !"sign-return-address", i32 0}
!7 = !{i32 8, !"sign-return-address-all", i32 0}
!8 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!9 = !{i32 7, !"uwtable", i32 1}
!10 = !{i32 7, !"frame-pointer", i32 1}
!11 = !{!"clang version 14.0.0"}

View File

@ -0,0 +1,16 @@
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
define dso_local i32 @foo() #0 {
entry:
ret i32 42
}
attributes #0 = { noinline nounwind optnone uwtable }
!llvm.module.flags = !{!0, !1, !2, !3}
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 1}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}

View File

@ -0,0 +1,38 @@
; Testcase to check that module with different branch-target-enforcement can
; be mixed.
;
; RUN: llvm-as %s -o %t1.bc
; RUN: llvm-as %p/Inputs/foo.ll -o %t2.bc
; RUN: llvm-lto -exported-symbol main \
; RUN: -exported-symbol foo \
; RUN: -filetype=obj \
; RUN: %t1.bc %t2.bc \
; RUN: -o %t1.exe 2>&1 | FileCheck --allow-empty %s
; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s
; RUN: llvm-readelf -n %t1.exe | FileCheck --check-prefix=CHECK-PROP %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
declare i32 @foo();
define i32 @main() {
entry:
%add = call i32 @foo()
ret i32 %add
}
!llvm.module.flags = !{!0, !1, !2, !3 }
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
; CHECK-NOT: linking module flags 'branch-target-enforcement': IDs have conflicting values in
; CHECK-DUMP: <main>:
; CHECK-DUMP: bl 0x8 <main+0x8>
; CHECK-DUMP: <foo>:
; `main` doesn't support BTI while `foo` does, so in the binary
; we should see only PAC which is supported by both.
; CHECK-PROP: Properties: aarch64 feature: PAC

View File

@ -0,0 +1,2 @@
if not 'AArch64' in config.root.targets:
config.unsupported = True

View File

@ -45,6 +45,10 @@
; CHECK: invalid value for 'max' module flag (expected constant integer)
!19 = !{i32 7, !"max", !"max"}
; Check that any 'min' module flags are valid.
; CHECK: invalid value for 'min' module flag (expected constant integer)
!20 = !{i32 8, !"min", !"min"}
; Check that any 'require' module flags are valid.
; CHECK: invalid requirement on flag, flag is not present in module
!11 = !{i32 3, !"bar", !{!"no-such-flag", i32 52}}
@ -58,4 +62,4 @@
!llvm.module.flags = !{
!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15,
!16, !17, !18, !19 }
!16, !17, !18, !19, !20 }