Skip to content

Commit f70baaf

Browse files
[AArch64] Add -mmark-bti-property flag.
Writing the .note.gnu.property manually is error prone and hard to maintain in the assembly files. The -mmark-bti-property is for the assembler to emit the section with the GNU_PROPERTY_AARCH64_FEATURE_1_BTI. To be used when C/C++ is compiled with -mbranch-protection=bti. This patch refactors the .note.gnu.property handling. Reviewed By: chill, nickdesaulniers Differential Revision: https://reviews.llvm.org/D81930 Reland with test dependency on aarch64 target.
1 parent 60e244f commit f70baaf

File tree

6 files changed

+99
-22
lines changed

6 files changed

+99
-22
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,9 @@ def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">,
23852385
def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
23862386
Group<m_aarch64_Features_Group>,
23872387
HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
2388+
def mmark_bti_property : Flag<["-"], "mmark-bti-property">,
2389+
Group<m_aarch64_Features_Group>,
2390+
HelpText<"Add .note.gnu.property with BTI to assembly files (AArch64 only)">;
23882391
foreach i = {1-31} in
23892392
def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_Group>,
23902393
HelpText<"Reserve the x"#i#" register (AArch64/RISC-V only)">;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7018,6 +7018,15 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
70187018
}
70197019
break;
70207020

7021+
case llvm::Triple::aarch64:
7022+
case llvm::Triple::aarch64_32:
7023+
case llvm::Triple::aarch64_be:
7024+
if (Args.hasArg(options::OPT_mmark_bti_property)) {
7025+
CmdArgs.push_back("-mllvm");
7026+
CmdArgs.push_back("-aarch64-mark-bti-property");
7027+
}
7028+
break;
7029+
70217030
case llvm::Triple::riscv32:
70227031
case llvm::Triple::riscv64:
70237032
AddRISCVTargetArgs(Args, CmdArgs);

clang/test/Driver/arm64-markbti.S

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// REQUIRES: aarch64-registered-target
2+
3+
// When -mmark-bti-property is passed the generated file object gets BTI marking.
4+
// RUN: %clang -target arm64-linux-none -mmark-bti-property -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_GEN %s
5+
// RUN: %clang -target arm64-linux-none -DNOTE_PRESENT -c %s -o - | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_PRESET %s
6+
// RUN: %clang -target arm64-linux-none -mmark-bti-property -DNOTE_PRESENT -c %s -o - | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_PRESET %s
7+
// RUN: %clang -target arm64-linux-none -mmark-bti-property -DNOTE_PRESENT -c %s -o - 2>&1 | FileCheck -check-prefix=CHECK_WARNING %s
8+
//
9+
// CHECK_WARNING: The .note.gnu.property is not emitted because it is already present.
10+
// CHECK: Name: .note.gnu.property
11+
// CHECK: Type: NT_GNU_PROPERTY_TYPE_0
12+
// CHECK_GEN: aarch64 feature: BTI
13+
// CHECK_PRESET: aarch64 feature: BTI, PAC
14+
15+
#ifdef NOTE_PRESENT
16+
.section .note.gnu.property, "a";
17+
.balign 8;
18+
.long 4;
19+
.long 0x10;
20+
.long 0x5
21+
.asciz "GNU"
22+
.long 0xc0000000
23+
.long 4
24+
.long 3
25+
.long 0
26+
#endif

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -223,26 +223,9 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
223223
return;
224224

225225
// Emit a .note.gnu.property section with the flags.
226-
MCSection *Cur = OutStreamer->getCurrentSectionOnly();
227-
MCSection *Nt = MMI->getContext().getELFSection(
228-
".note.gnu.property", ELF::SHT_NOTE, ELF::SHF_ALLOC);
229-
OutStreamer->SwitchSection(Nt);
230-
231-
// Emit the note header.
232-
emitAlignment(Align(8));
233-
OutStreamer->emitInt32(4); // data size for "GNU\0"
234-
OutStreamer->emitInt32(4 * 4); // Elf_Prop size
235-
OutStreamer->emitInt32(ELF::NT_GNU_PROPERTY_TYPE_0);
236-
OutStreamer->emitBytes(StringRef("GNU", 4)); // note name
237-
238-
// Emit the PAC/BTI properties.
239-
OutStreamer->emitInt32(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND);
240-
OutStreamer->emitInt32(4); // data size
241-
OutStreamer->emitInt32(Flags); // data
242-
OutStreamer->emitInt32(0); // pad
243-
244-
OutStreamer->endSection(Nt);
245-
OutStreamer->SwitchSection(Cur);
226+
if (auto *TS = static_cast<AArch64TargetStreamer *>(
227+
OutStreamer->getTargetStreamer()))
228+
TS->emitNoteSection(Flags);
246229
}
247230

248231
void AArch64AsmPrinter::emitFunctionHeaderComment() {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,23 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "AArch64TargetStreamer.h"
14+
#include "AArch64MCAsmInfo.h"
15+
#include "AArch64Subtarget.h"
16+
#include "llvm/BinaryFormat/ELF.h"
1417
#include "llvm/MC/ConstantPools.h"
18+
#include "llvm/MC/MCContext.h"
1519
#include "llvm/MC/MCSection.h"
20+
#include "llvm/MC/MCSectionELF.h"
1621
#include "llvm/MC/MCSubtargetInfo.h"
22+
#include "llvm/Support/CommandLine.h"
1723

1824
using namespace llvm;
1925

26+
static cl::opt<bool> MarkBTIProperty(
27+
"aarch64-mark-bti-property", cl::Hidden,
28+
cl::desc("Add .note.gnu.property with BTI to assembly files"),
29+
cl::init(false));
30+
2031
//
2132
// AArch64TargetStreamer Implemenation
2233
//
@@ -37,8 +48,50 @@ void AArch64TargetStreamer::emitCurrentConstantPool() {
3748
ConstantPools->emitForCurrentSection(Streamer);
3849
}
3950

40-
// finish() - write out any non-empty assembler constant pools.
41-
void AArch64TargetStreamer::finish() { ConstantPools->emitAll(Streamer); }
51+
// finish() - write out any non-empty assembler constant pools and
52+
// write out note.gnu.properties if need.
53+
void AArch64TargetStreamer::finish() {
54+
ConstantPools->emitAll(Streamer);
55+
56+
if (MarkBTIProperty)
57+
emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
58+
}
59+
60+
void AArch64TargetStreamer::emitNoteSection(unsigned Flags) {
61+
if (Flags == 0)
62+
return;
63+
64+
MCStreamer &OutStreamer = getStreamer();
65+
MCContext &Context = OutStreamer.getContext();
66+
// Emit a .note.gnu.property section with the flags.
67+
MCSectionELF *Nt = Context.getELFSection(".note.gnu.property", ELF::SHT_NOTE,
68+
ELF::SHF_ALLOC);
69+
if (Nt->isRegistered()) {
70+
SMLoc Loc;
71+
Context.reportWarning(
72+
Loc,
73+
"The .note.gnu.property is not emitted because it is already present.");
74+
return;
75+
}
76+
MCSection *Cur = OutStreamer.getCurrentSectionOnly();
77+
OutStreamer.SwitchSection(Nt);
78+
79+
// Emit the note header.
80+
OutStreamer.emitValueToAlignment(Align(8).value());
81+
OutStreamer.emitIntValue(4, 4); // data size for "GNU\0"
82+
OutStreamer.emitIntValue(4 * 4, 4); // Elf_Prop size
83+
OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4);
84+
OutStreamer.emitBytes(StringRef("GNU", 4)); // note name
85+
86+
// Emit the PAC/BTI properties.
87+
OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);
88+
OutStreamer.emitIntValue(4, 4); // data size
89+
OutStreamer.emitIntValue(Flags, 4); // data
90+
OutStreamer.emitIntValue(0, 4); // pad
91+
92+
OutStreamer.endSection(Nt);
93+
OutStreamer.SwitchSection(Cur);
94+
}
4295

4396
void AArch64TargetStreamer::emitInst(uint32_t Inst) {
4497
char Buffer[4];

llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class AArch64TargetStreamer : public MCTargetStreamer {
3333
/// Emit contents of constant pool for the current section.
3434
void emitCurrentConstantPool();
3535

36+
/// Callback used to implement the .note.gnu.property section.
37+
void emitNoteSection(unsigned Flags);
38+
3639
/// Callback used to implement the .inst directive.
3740
virtual void emitInst(uint32_t Inst);
3841

0 commit comments

Comments
 (0)