Skip to content

[PAC][ELF][AArch64] Support signed personality function pointer #119361

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

Merged
merged 3 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,9 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1);

if (getTriple().isOSLinux()) {
if (LangOpts.PointerAuthCalls)
getModule().addModuleFlag(llvm::Module::Min, "ptrauth-sign-personality",
1);
assert(getTriple().isOSBinFormatELF());
using namespace llvm::ELF;
uint64_t PAuthABIVersion =
Expand Down
5 changes: 5 additions & 0 deletions clang/test/CodeGen/ptrauth-module-flags.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefix=PERSONALITY

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

// PERSONALITY: !llvm.module.flags = !{
// PERSONALITY-SAME: !1
// PERSONALITY: !1 = !{i32 8, !"ptrauth-sign-personality", i32 1}

// OFF-NOT: "ptrauth-
8 changes: 7 additions & 1 deletion llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,14 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
/// extern_weak symbols.
DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;

/// HasSignedPersonality is true if the corresponding IR module has the
/// "ptrauth-sign-personality" flag set to 1.
bool HasSignedPersonality = false;

virtual void anchor(); // Out of line virtual method.

public:
MachineModuleInfoELF(const MachineModuleInfo &) {}
MachineModuleInfoELF(const MachineModuleInfo &);

StubValueTy &getGVStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
Expand All @@ -105,6 +109,8 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
ExprStubListTy getAuthGVStubList() {
return getSortedExprStubs(AuthPtrStubs);
}

bool hasSignedPersonality() const { return HasSignedPersonality; }
};

/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation
Expand Down
8 changes: 7 additions & 1 deletion llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;

void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL,
const MCSymbol *Sym) const override;
const MCSymbol *Sym,
const MachineModuleInfo *MMI) const override;

virtual void emitPersonalityValueImpl(MCStreamer &Streamer,
const DataLayout &DL,
const MCSymbol *Sym,
const MachineModuleInfo *MMI) const;

/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Target/TargetLoweringObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
virtual void Initialize(MCContext &ctx, const TargetMachine &TM);

virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
const MCSymbol *Sym) const;
const MCSymbol *Sym,
const MachineModuleInfo *MMI) const;

/// Emit the module-level metadata that the platform cares about.
virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ void DwarfCFIException::endModule() {
// Emit indirect reference table for all used personality functions
for (const GlobalValue *Personality : Personalities) {
MCSymbol *Sym = Asm->getSymbol(Personality);
TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym,
Asm->MMI);
}
Personalities.clear();
}
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCSymbol.h"

using namespace llvm;
Expand Down Expand Up @@ -59,3 +61,10 @@ MachineModuleInfoImpl::ExprStubListTy MachineModuleInfoImpl::getSortedExprStubs(
ExprStubs.clear();
return List;
}

MachineModuleInfoELF::MachineModuleInfoELF(const MachineModuleInfo &MMI) {
const Module *M = MMI.getModule();
const auto *Flag = mdconst::extract_or_null<ConstantInt>(
M->getModuleFlag("ptrauth-sign-personality"));
HasSignedPersonality = Flag && Flag->getZExtValue() == 1;
}
11 changes: 9 additions & 2 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@ MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
}

void TargetLoweringObjectFileELF::emitPersonalityValue(
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym) const {
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
const MachineModuleInfo *MMI) const {
SmallString<64> NameData("DW.ref.");
NameData += Sym->getName();
MCSymbolELF *Label =
Expand All @@ -431,7 +432,13 @@ void TargetLoweringObjectFileELF::emitPersonalityValue(
Streamer.emitELFSize(Label, E);
Streamer.emitLabel(Label);

Streamer.emitSymbolValue(Sym, Size);
emitPersonalityValueImpl(Streamer, DL, Sym, MMI);
}

void TargetLoweringObjectFileELF::emitPersonalityValueImpl(
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
const MachineModuleInfo *MMI) const {
Streamer.emitSymbolValue(Sym, DL.getPointerSize());
}

const MCExpr *TargetLoweringObjectFileELF::getTTypeGlobalReference(
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "AArch64TargetObjectFile.h"
#include "AArch64TargetMachine.h"
#include "MCTargetDesc/AArch64MCExpr.h"
#include "MCTargetDesc/AArch64TargetStreamer.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/Mangler.h"
Expand All @@ -28,6 +29,21 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
SupportDebugThreadLocalLocation = false;
}

void AArch64_ELFTargetObjectFile::emitPersonalityValueImpl(
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
const MachineModuleInfo *MMI) const {
if (!MMI->getObjFileInfo<MachineModuleInfoELF>().hasSignedPersonality()) {
TargetLoweringObjectFileELF::emitPersonalityValueImpl(Streamer, DL, Sym,
MMI);
return;
}
auto *TS = static_cast<AArch64TargetStreamer *>(Streamer.getTargetStreamer());
// The value is ptrauth_string_discriminator("personality")
constexpr uint16_t Discriminator = 0x7EAD;
TS->emitAuthValue(MCSymbolRefExpr::create(Sym, getContext()), Discriminator,
AArch64PACKey::IA, /*HasAddressDiversity=*/true);
}

const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
MachineModuleInfo *MMI, const MCSymbol *RawSym,
AArch64PACKey::ID Key,
uint16_t Discriminator) const;

void emitPersonalityValueImpl(MCStreamer &Streamer, const DataLayout &DL,
const MCSymbol *Sym,
const MachineModuleInfo *MMI) const override;
};

/// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer &S)

AArch64TargetStreamer::~AArch64TargetStreamer() = default;

void AArch64TargetStreamer::emitAuthValue(const MCExpr *Expr,
uint16_t Discriminator,
AArch64PACKey::ID Key,
bool HasAddressDiversity) {
Streamer.emitValueImpl(AArch64AuthMCExpr::create(Expr, Discriminator, Key,
HasAddressDiversity,
Streamer.getContext()),
8);
}

// The constant pool handling is shared by all AArch64TargetStreamer
// implementations.
const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr,
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H

#include "AArch64MCExpr.h"
#include "llvm/MC/MCStreamer.h"

namespace {
Expand Down Expand Up @@ -38,6 +39,11 @@ class AArch64TargetStreamer : public MCTargetStreamer {
void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform = -1,
uint64_t PAuthABIVersion = -1);

/// Callback used to emit AUTH expressions (e.g. signed
/// personality function pointer).
void emitAuthValue(const MCExpr *Expr, uint16_t Discriminator,
AArch64PACKey::ID Key, bool HasAddressDiversity);

/// Callback used to implement the .inst directive.
virtual void emitInst(uint32_t Inst);

Expand Down
7 changes: 3 additions & 4 deletions llvm/lib/Target/TargetLoweringObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,9 @@ MCSymbol *TargetLoweringObjectFile::getCFIPersonalitySymbol(
return TM.getSymbol(GV);
}

void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer,
const DataLayout &,
const MCSymbol *Sym) const {
}
void TargetLoweringObjectFile::emitPersonalityValue(
MCStreamer &Streamer, const DataLayout &, const MCSymbol *Sym,
const MachineModuleInfo *MMI) const {}

void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,
Module &M) const {
Expand Down
73 changes: 73 additions & 0 deletions llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
; RUN: rm -rf %t && split-file %s %t && cd %t
; RUN: cat common.ll authflag.ll > auth.ll
; RUN: cat common.ll noauthflag.ll > noauth1.ll
; RUN: cat common.ll > noauth2.ll

; RUN: llc -mtriple=aarch64-linux -filetype=asm auth.ll -o - | \
; RUN: FileCheck --check-prefix=AUTH-ASM %s
; RUN: llc -mtriple=aarch64-linux -filetype=obj auth.ll -o - | \
; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \
; RUN: FileCheck --check-prefix=AUTH-RELOC %s

; AUTH-ASM: DW.ref.__gxx_personality_v0:
; AUTH-ASM-NEXT: .xword __gxx_personality_v0@AUTH(ia,32429,addr)

; AUTH-RELOC: Relocation section '.rela.data.DW.ref.__gxx_personality_v0' at offset 0x2a0 contains 1 entries:
; AUTH-RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
; AUTH-RELOC-NEXT: 0000000000000000 0000000f00000244 R_AARCH64_AUTH_ABS64 0000000000000000 __gxx_personality_v0 + 0

; AUTH-RELOC: Hex dump of section '.data.DW.ref.__gxx_personality_v0':
; AUTH-RELOC-NEXT: 0x00000000 00000000 ad7e0080
; ^^^^ 0x7EAD = discriminator
; ^^ 0b10000000: bit 63 = 1 -> address diversity enabled, bits 61:60 = 0b00 -> key is IA

; RUN: llc -mtriple=aarch64-linux -filetype=asm noauth1.ll -o - | \
; RUN: FileCheck --check-prefix=NOAUTH-ASM %s
; RUN: llc -mtriple=aarch64-linux -filetype=obj noauth1.ll -o - | \
; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \
; RUN: FileCheck --check-prefix=NOAUTH-RELOC %s

; RUN: llc -mtriple=aarch64-linux -filetype=asm noauth2.ll -o - | \
; RUN: FileCheck --check-prefix=NOAUTH-ASM %s
; RUN: llc -mtriple=aarch64-linux -filetype=obj noauth2.ll -o - | \
; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \
; RUN: FileCheck --check-prefix=NOAUTH-RELOC %s

; NOAUTH-ASM: DW.ref.__gxx_personality_v0:
; NOAUTH-ASM-NEXT: .xword __gxx_personality_v0{{$}}

; NOAUTH-RELOC: Relocation section '.rela.data.DW.ref.__gxx_personality_v0' at offset 0x2a0 contains 1 entries:
; NOAUTH-RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
; NOAUTH-RELOC-NEXT: 0000000000000000 0000000f00000101 R_AARCH64_ABS64 0000000000000000 __gxx_personality_v0 + 0

; NOAUTH-RELOC: Hex dump of section '.data.DW.ref.__gxx_personality_v0':
; NOAUTH-RELOC-NEXT: 0x00000000 00000000 00000000

;--- common.ll
@_ZTISt9exception = external constant ptr

define i32 @main() personality ptr @__gxx_personality_v0 {
entry:
invoke void @foo() to label %cont unwind label %lpad

lpad:
%0 = landingpad { ptr, i32 }
catch ptr null
catch ptr @_ZTISt9exception
ret i32 0

cont:
ret i32 0
}

declare i32 @__gxx_personality_v0(...)

declare void @foo()

;--- authflag.ll
!llvm.module.flags = !{!0}
!0 = !{i32 8, !"ptrauth-sign-personality", i32 1}

;--- noauthflag.ll
!llvm.module.flags = !{!0}
!0 = !{i32 8, !"ptrauth-sign-personality", i32 0}
Loading