Skip to content

Commit 4fb1cda

Browse files
authored
[PAC][ELF][AArch64] Support signed personality function pointer (#113148)
If function pointer signing is enabled, sign personality function pointer stored in `.DW.ref.__gxx_personality_v0` section with IA key, 0x7EAD = `ptrauth_string_discriminator("personality")` constant discriminator and address diversity enabled.
1 parent 7fa5743 commit 4fb1cda

16 files changed

+176
-8
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,9 @@ void CodeGenModule::Release() {
12181218
getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1);
12191219

12201220
if (getTriple().isOSLinux()) {
1221+
if (LangOpts.PointerAuthCalls)
1222+
getModule().addModuleFlag(llvm::Module::Min, "ptrauth-sign-personality",
1223+
1);
12211224
assert(getTriple().isOSBinFormatELF());
12221225
using namespace llvm::ELF;
12231226
uint64_t PAuthABIVersion =
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF
22
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT
3+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefix=PERSONALITY
34

45
// ELFGOT: !llvm.module.flags = !{
56
// ELFGOT-SAME: !1
67
// ELFGOT: !1 = !{i32 8, !"ptrauth-elf-got", i32 1}
78

9+
// PERSONALITY: !llvm.module.flags = !{
10+
// PERSONALITY-SAME: !1
11+
// PERSONALITY: !1 = !{i32 8, !"ptrauth-sign-personality", i32 1}
12+
813
// OFF-NOT: "ptrauth-

llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
5252
void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
5353

5454
void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL,
55-
const MCSymbol *Sym) const override;
55+
const MCSymbol *Sym,
56+
const MachineModuleInfo *MMI) const override;
57+
58+
virtual void emitPersonalityValueImpl(MCStreamer &Streamer,
59+
const DataLayout &DL,
60+
const MCSymbol *Sym,
61+
const MachineModuleInfo *MMI) const;
5662

5763
/// Given a constant with the SectionKind, return a section that it should be
5864
/// placed in.

llvm/include/llvm/Target/TargetLoweringObjectFile.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
8282
virtual void Initialize(MCContext &ctx, const TargetMachine &TM);
8383

8484
virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
85-
const MCSymbol *Sym) const;
85+
const MCSymbol *Sym,
86+
const MachineModuleInfo *MMI) const;
8687

8788
/// Emit the module-level metadata that the platform cares about.
8889
virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}

llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ void DwarfCFIException::endModule() {
5050
// Emit indirect reference table for all used personality functions
5151
for (const GlobalValue *Personality : Personalities) {
5252
MCSymbol *Sym = Asm->getSymbol(Personality);
53-
TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
53+
TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym,
54+
Asm->MMI);
5455
}
5556
Personalities.clear();
5657
}

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
413413
}
414414

415415
void TargetLoweringObjectFileELF::emitPersonalityValue(
416-
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym) const {
416+
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
417+
const MachineModuleInfo *MMI) const {
417418
SmallString<64> NameData("DW.ref.");
418419
NameData += Sym->getName();
419420
MCSymbolELF *Label =
@@ -431,6 +432,13 @@ void TargetLoweringObjectFileELF::emitPersonalityValue(
431432
Streamer.emitELFSize(Label, E);
432433
Streamer.emitLabel(Label);
433434

435+
emitPersonalityValueImpl(Streamer, DL, Sym, MMI);
436+
}
437+
438+
void TargetLoweringObjectFileELF::emitPersonalityValueImpl(
439+
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
440+
const MachineModuleInfo *MMI) const {
441+
unsigned Size = DL.getPointerSize();
434442
Streamer.emitSymbolValue(Sym, Size);
435443
}
436444

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===--- AArch64MachineModuleInfo.cpp ---------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file
10+
/// AArch64 Machine Module Info.
11+
///
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "AArch64MachineModuleInfo.h"
16+
#include "llvm/IR/Constants.h"
17+
#include "llvm/IR/Module.h"
18+
19+
namespace llvm {
20+
21+
AArch64MachineModuleInfo::AArch64MachineModuleInfo(const MachineModuleInfo &MMI)
22+
: MachineModuleInfoELF(MMI) {
23+
const Module *M = MMI.getModule();
24+
const auto *Flag = mdconst::extract_or_null<ConstantInt>(
25+
M->getModuleFlag("ptrauth-sign-personality"));
26+
if (Flag && Flag->getZExtValue() == 1)
27+
HasSignedPersonality = true;
28+
else
29+
HasSignedPersonality = false;
30+
}
31+
32+
} // end namespace llvm
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===--- AArch64MachineModuleInfo.h -----------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file
10+
/// AArch64 Machine Module Info.
11+
///
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEMODULEINFO_H
16+
#define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEMODULEINFO_H
17+
18+
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
19+
20+
namespace llvm {
21+
22+
class AArch64MachineModuleInfo final : public MachineModuleInfoELF {
23+
/// HasSignedPersonality is true if the corresponding IR module has the
24+
/// "ptrauth-sign-personality" flag set to 1.
25+
bool HasSignedPersonality = false;
26+
27+
public:
28+
AArch64MachineModuleInfo(const MachineModuleInfo &);
29+
30+
bool hasSignedPersonality() const { return HasSignedPersonality; }
31+
};
32+
33+
} // end namespace llvm
34+
35+
#endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEMODULEINFO_H

llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "AArch64TargetObjectFile.h"
10+
#include "AArch64MachineModuleInfo.h"
1011
#include "AArch64TargetMachine.h"
1112
#include "MCTargetDesc/AArch64MCExpr.h"
13+
#include "MCTargetDesc/AArch64TargetStreamer.h"
1214
#include "llvm/BinaryFormat/Dwarf.h"
1315
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
1416
#include "llvm/IR/Mangler.h"
@@ -28,6 +30,21 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
2830
SupportDebugThreadLocalLocation = false;
2931
}
3032

33+
void AArch64_ELFTargetObjectFile::emitPersonalityValueImpl(
34+
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
35+
const MachineModuleInfo *MMI) const {
36+
if (!MMI->getObjFileInfo<AArch64MachineModuleInfo>().hasSignedPersonality()) {
37+
TargetLoweringObjectFileELF::emitPersonalityValueImpl(Streamer, DL, Sym,
38+
MMI);
39+
return;
40+
}
41+
auto *TS = static_cast<AArch64TargetStreamer *>(Streamer.getTargetStreamer());
42+
// The value is ptrauth_string_discriminator("personality")
43+
constexpr uint16_t Discriminator = 0x7EAD;
44+
TS->emitAuthValue(MCSymbolRefExpr::create(Sym, getContext()), Discriminator,
45+
AArch64PACKey::IA, /*HasAddressDiversity=*/true);
46+
}
47+
3148
const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
3249
const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
3350
int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {

llvm/lib/Target/AArch64/AArch64TargetObjectFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
3535
MachineModuleInfo *MMI, const MCSymbol *RawSym,
3636
AArch64PACKey::ID Key,
3737
uint16_t Discriminator) const;
38+
39+
void emitPersonalityValueImpl(MCStreamer &Streamer, const DataLayout &DL,
40+
const MCSymbol *Sym,
41+
const MachineModuleInfo *MMI) const override;
3842
};
3943

4044
/// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.

llvm/lib/Target/AArch64/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ add_llvm_target(AArch64CodeGen
6767
AArch64LoadStoreOptimizer.cpp
6868
AArch64LowerHomogeneousPrologEpilog.cpp
6969
AArch64MachineFunctionInfo.cpp
70+
AArch64MachineModuleInfo.cpp
7071
AArch64MachineScheduler.cpp
7172
AArch64MacroFusion.cpp
7273
AArch64MIPeepholeOpt.cpp

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer &S)
3535

3636
AArch64TargetStreamer::~AArch64TargetStreamer() = default;
3737

38+
void AArch64TargetStreamer::emitAuthValue(const MCExpr *Expr,
39+
uint16_t Discriminator,
40+
AArch64PACKey::ID Key,
41+
bool HasAddressDiversity) {
42+
Streamer.emitValueImpl(AArch64AuthMCExpr::create(Expr, Discriminator, Key,
43+
HasAddressDiversity,
44+
Streamer.getContext()),
45+
8);
46+
}
47+
3848
// The constant pool handling is shared by all AArch64TargetStreamer
3949
// implementations.
4050
const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr,

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
1010
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
1111

12+
#include "AArch64MCExpr.h"
1213
#include "llvm/MC/MCStreamer.h"
1314

1415
namespace {
@@ -38,6 +39,11 @@ class AArch64TargetStreamer : public MCTargetStreamer {
3839
void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform = -1,
3940
uint64_t PAuthABIVersion = -1);
4041

42+
/// Callback used to emit AUTH expressions (e.g. signed
43+
/// personality function pointer).
44+
void emitAuthValue(const MCExpr *Expr, uint16_t Discriminator,
45+
AArch64PACKey::ID Key, bool HasAddressDiversity);
46+
4147
/// Callback used to implement the .inst directive.
4248
virtual void emitInst(uint32_t Inst);
4349

llvm/lib/Target/TargetLoweringObjectFile.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,9 @@ MCSymbol *TargetLoweringObjectFile::getCFIPersonalitySymbol(
141141
return TM.getSymbol(GV);
142142
}
143143

144-
void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer,
145-
const DataLayout &,
146-
const MCSymbol *Sym) const {
147-
}
144+
void TargetLoweringObjectFile::emitPersonalityValue(
145+
MCStreamer &Streamer, const DataLayout &, const MCSymbol *Sym,
146+
const MachineModuleInfo *MMI) const {}
148147

149148
void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,
150149
Module &M) const {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: llc -mtriple=aarch64-linux -filetype=asm %s -o - | FileCheck %s
2+
; RUN: llc -mtriple=aarch64-linux -filetype=obj %s -o - | \
3+
; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \
4+
; RUN: FileCheck --check-prefix=RELOC %s
5+
6+
@_ZTISt9exception = external constant ptr
7+
8+
define i32 @main() personality ptr @__gxx_personality_v0 {
9+
entry:
10+
invoke void @foo() to label %cont unwind label %lpad
11+
12+
lpad:
13+
%0 = landingpad { ptr, i32 }
14+
catch ptr null
15+
catch ptr @_ZTISt9exception
16+
ret i32 0
17+
18+
cont:
19+
ret i32 0
20+
}
21+
22+
declare i32 @__gxx_personality_v0(...)
23+
24+
declare void @foo()
25+
26+
!llvm.module.flags = !{!0}
27+
!0 = !{i32 8, !"ptrauth-sign-personality", i32 1}
28+
29+
; CHECK: DW.ref.__gxx_personality_v0:
30+
; CHECK-NEXT: .xword __gxx_personality_v0@AUTH(ia,32429,addr)
31+
32+
; RELOC: Relocation section '.rela.data.DW.ref.__gxx_personality_v0' at offset 0x2a0 contains 1 entries:
33+
; RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
34+
; RELOC-NEXT: 0000000000000000 0000000f00000244 R_AARCH64_AUTH_ABS64 0000000000000000 __gxx_personality_v0 + 0
35+
36+
; RELOC: Hex dump of section '.data.DW.ref.__gxx_personality_v0':
37+
; RELOC-NEXT: 0x00000000 00000000 ad7e0080
38+
; ^^^^ 0x7EAD = discriminator
39+
; ^^ 0b10000000: bit 63 = 1 -> address diversity enabled, bits 61:60 = 0b00 -> key is IA

llvm/utils/gn/secondary/llvm/lib/Target/AArch64/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ static_library("LLVMAArch64CodeGen") {
135135
"AArch64MCInstLower.cpp",
136136
"AArch64MIPeepholeOpt.cpp",
137137
"AArch64MachineFunctionInfo.cpp",
138+
"AArch64MachineModuleInfo.cpp",
138139
"AArch64MachineScheduler.cpp",
139140
"AArch64MacroFusion.cpp",
140141
"AArch64PBQPRegAlloc.cpp",

0 commit comments

Comments
 (0)