https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/84384
>From ef23d427b48687b62da9e1062886ddfcc1649b6a Mon Sep 17 00:00:00 2001 From: John McCall <rjmcc...@apple.com> Date: Mon, 16 Dec 2019 20:31:25 -0500 Subject: [PATCH 1/4] Abstract serialization fixes for the Apple Clang changes. --- clang/include/clang/AST/AbstractBasicReader.h | 4 ++-- clang/include/clang/AST/AbstractBasicWriter.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index 1f2797cc701458..ab036f1d445acc 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -213,9 +213,9 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> { } Qualifiers readQualifiers() { - static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t), + static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t), "update this if the value size changes"); - uint32_t value = asImpl().readUInt32(); + uint64_t value = asImpl().readUInt64(); return Qualifiers::fromOpaqueValue(value); } diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index 07afa388de2c17..8e42fcaad1d388 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -196,9 +196,9 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> { } void writeQualifiers(Qualifiers value) { - static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t), + static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t), "update this if the value size changes"); - asImpl().writeUInt32(value.getAsOpaqueValue()); + asImpl().writeUInt64(value.getAsOpaqueValue()); } void writeExceptionSpecInfo( >From 9e296a1a69158419960c265f12f52523db0c8e2a Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Thu, 7 Mar 2024 15:34:24 +0300 Subject: [PATCH 2/4] [clang] Define `PointerAuthenticationMode` enum --- clang/include/clang/Basic/LangOptions.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 862952d336ef31..6fe7472d8ad0ca 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -57,6 +57,13 @@ enum class ShaderStage { Invalid, }; +enum class PointerAuthenticationMode : unsigned { + None, + Strip, + SignAndStrip, + SignAndAuth +}; + /// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// this large collection of bitfields is a trivial class type. class LangOptionsBase { >From 71d7760aa9cc459d7bc0365fa079f64cb5704c96 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Thu, 7 Mar 2024 15:31:03 +0300 Subject: [PATCH 3/4] [clang] Define `PointerAuthQualifier` class Includes changes from the following commits from the branch https://github.com/ahmedbougacha/llvm-project/tree/eng/arm64e-upstream-llvmorg - Initial support https://github.com/ahmedbougacha/llvm-project/commit/cc7ba7eb1814e9b254c7d94aa0b78cb0e21acfc5 - ObjC isa signing https://github.com/ahmedbougacha/llvm-project/commit/c9ce0d408f1d9aeffc7b86256334220aec6de5a3 Also applies a fix from https://github.com/access-softek/llvm-project/pull/75 Co-authored-by: Ahmed Bougacha <ah...@bougacha.org> --- clang/include/clang/AST/Type.h | 215 +++++++++++++++++- .../include/clang/Basic/PointerAuthOptions.h | 23 ++ 2 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 clang/include/clang/Basic/PointerAuthOptions.h diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 1942b0e67f65a3..1741a3017f7280 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -25,8 +25,10 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/PointerAuthOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" @@ -138,6 +140,165 @@ using CanQualType = CanQual<Type>; #define TYPE(Class, Base) class Class##Type; #include "clang/AST/TypeNodes.inc" +/// Pointer-authentication qualifiers. +class PointerAuthQualifier { + enum : uint32_t { + EnabledShift = 0, + EnabledBits = 1, + EnabledMask = 1 << EnabledShift, + AddressDiscriminatedShift = EnabledShift + EnabledBits, + AddressDiscriminatedBits = 1, + AddressDiscriminatedMask = 1 << AddressDiscriminatedShift, + AuthenticationModeShift = + AddressDiscriminatedShift + AddressDiscriminatedBits, + AuthenticationModeBits = 2, + AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1) + << AuthenticationModeShift, + IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits, + IsaPointerBits = 1, + IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift, + AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits, + AuthenticatesNullValuesBits = 1, + AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1) + << AuthenticatesNullValuesShift, + KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits, + KeyBits = 10, + KeyMask = ((1 << KeyBits) - 1) << KeyShift, + DiscriminatorShift = KeyShift + KeyBits, + DiscriminatorBits = 16, + DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift, + }; + + // bits: |0 |1 |2..3 |4 | + // |Enabled|Address|AuthenticationMode|ISA pointer| + // bits: |5 |6..15| 16...31 | + // |AuthenticatesNull|Key |Discriminator| + uint32_t Data; + + static_assert((EnabledBits + AddressDiscriminatedBits + + AuthenticationModeBits + IsaPointerBits + + AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) == + 32, + "PointerAuthQualifier should be exactly 32 bits"); + static_assert((EnabledMask + AddressDiscriminatedMask + + AuthenticationModeMask + IsaPointerMask + + AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) == + 0xFFFFFFFF, + "All masks should cover the entire bits"); + static_assert((EnabledMask ^ AddressDiscriminatedMask ^ + AuthenticationModeMask ^ IsaPointerMask ^ + AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) == + 0xFFFFFFFF, + "All masks should cover the entire bits"); + + PointerAuthQualifier(unsigned key, bool isAddressDiscriminated, + unsigned extraDiscriminator, + PointerAuthenticationMode authenticationMode, + bool isIsaPointer, bool authenticatesNullValues) + : Data(EnabledMask | + (isAddressDiscriminated + ? static_cast<uint32_t>(AddressDiscriminatedMask) + : 0) | + (key << KeyShift) | + (unsigned(authenticationMode) << AuthenticationModeShift) | + (extraDiscriminator << DiscriminatorShift) | + (isIsaPointer << IsaPointerShift) | + (authenticatesNullValues << AuthenticatesNullValuesShift)) { + assert(key <= KeyNoneInternal); + assert(extraDiscriminator <= MaxDiscriminator); + } + +public: + enum { + KeyNoneInternal = (1u << KeyBits) - 1, + + /// The maximum supported pointer-authentication key. + MaxKey = KeyNoneInternal - 1, + + /// The maximum supported pointer-authentication discriminator. + MaxDiscriminator = (1u << DiscriminatorBits) - 1 + }; + +public: + PointerAuthQualifier() : Data(0) {} + + static PointerAuthQualifier + Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator, + PointerAuthenticationMode authenticationMode, bool isIsaPointer, + bool authenticatesNullValues) { + if (key == PointerAuthKeyNone) + key = KeyNoneInternal; + assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value"); + return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator, + authenticationMode, isIsaPointer, + authenticatesNullValues); + } + + bool isPresent() const { + return getAuthenticationMode() != PointerAuthenticationMode::None; + } + + explicit operator bool() const { return isPresent(); } + + unsigned getKey() const { + assert(isPresent()); + return (Data & KeyMask) >> KeyShift; + } + + bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; } + + bool isAddressDiscriminated() const { + assert(isPresent()); + return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift; + } + + unsigned getExtraDiscriminator() const { + assert(isPresent()); + return (Data >> DiscriminatorShift); + } + + PointerAuthenticationMode getAuthenticationMode() const { + return PointerAuthenticationMode((Data & AuthenticationModeMask) >> + AuthenticationModeShift); + } + + bool isIsaPointer() const { + assert(isPresent()); + return (Data & IsaPointerMask) >> IsaPointerShift; + } + + bool authenticatesNullValues() const { + assert(isPresent()); + return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift; + } + + PointerAuthQualifier withoutKeyNone() const { + return hasKeyNone() ? PointerAuthQualifier() : *this; + } + + friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) { + return Lhs.Data == Rhs.Data; + } + friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) { + return Lhs.Data != Rhs.Data; + } + + bool isEquivalent(PointerAuthQualifier Other) const { + return withoutKeyNone() == Other.withoutKeyNone(); + } + + uint32_t getAsOpaqueValue() const { return Data; } + + // Deserialize pointer-auth qualifiers from an opaque representation. + static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) { + PointerAuthQualifier result; + result.Data = opaque; + return result; + } + + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); } +}; + /// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: /// * C99: const, volatile, and restrict @@ -193,19 +354,27 @@ class Qualifiers { FastMask = (1 << FastWidth) - 1 }; + Qualifiers() : Mask(0), PtrAuth() {} + /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { + Qualifiers Q; + if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) { + Q.setPointerAuth(L.getPointerAuth().withoutKeyNone()); + PointerAuthQualifier Empty; + L.setPointerAuth(Empty); + R.setPointerAuth(Empty); + } + // If both are only CVR-qualified, bit operations are sufficient. if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) { - Qualifiers Q; Q.Mask = L.Mask & R.Mask; L.Mask &= ~Q.Mask; R.Mask &= ~Q.Mask; return Q; } - Qualifiers Q; unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers(); Q.addCVRQualifiers(CommonCRV); L.removeCVRQualifiers(CommonCRV); @@ -250,15 +419,16 @@ class Qualifiers { } // Deserialize qualifiers from an opaque representation. - static Qualifiers fromOpaqueValue(unsigned opaque) { + static Qualifiers fromOpaqueValue(uint64_t opaque) { Qualifiers Qs; - Qs.Mask = opaque; + Qs.Mask = uint32_t(opaque); + Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32)); return Qs; } // Serialize these qualifiers into an opaque representation. - unsigned getAsOpaqueValue() const { - return Mask; + uint64_t getAsOpaqueValue() const { + return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32); } bool hasConst() const { return Mask & Const; } @@ -406,6 +576,10 @@ class Qualifiers { setAddressSpace(space); } + PointerAuthQualifier getPointerAuth() const { return PtrAuth; } + void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; } + void removePtrAuth() { PtrAuth = PointerAuthQualifier(); } + // Fast qualifiers are those that can be allocated directly // on a QualType object. bool hasFastQualifiers() const { return getFastQualifiers(); } @@ -428,7 +602,7 @@ class Qualifiers { /// Return true if the set contains any qualifiers which require an ExtQuals /// node to be allocated. - bool hasNonFastQualifiers() const { return Mask & ~FastMask; } + bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; } Qualifiers getNonFastQualifiers() const { Qualifiers Quals = *this; Quals.setFastQualifiers(0); @@ -436,8 +610,8 @@ class Qualifiers { } /// Return true if the set contains any qualifiers. - bool hasQualifiers() const { return Mask; } - bool empty() const { return !Mask; } + bool hasQualifiers() const { return Mask || PtrAuth; } + bool empty() const { return !hasQualifiers(); } /// Add the qualifiers from the given set to this set. void addQualifiers(Qualifiers Q) { @@ -454,6 +628,9 @@ class Qualifiers { if (Q.hasObjCLifetime()) addObjCLifetime(Q.getObjCLifetime()); } + + if (Q.PtrAuth) + PtrAuth = Q.PtrAuth; } /// Remove the qualifiers from the given set from this set. @@ -471,6 +648,9 @@ class Qualifiers { if (getAddressSpace() == Q.getAddressSpace()) removeAddressSpace(); } + + if (PtrAuth == Q.PtrAuth) + PtrAuth = PointerAuthQualifier(); } /// Add the qualifiers from the given set to this set, given that @@ -482,7 +662,10 @@ class Qualifiers { !hasObjCGCAttr() || !qs.hasObjCGCAttr()); assert(getObjCLifetime() == qs.getObjCLifetime() || !hasObjCLifetime() || !qs.hasObjCLifetime()); + assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth); Mask |= qs.Mask; + if (qs.PtrAuth) + PtrAuth = qs.PtrAuth; } /// Returns true if address space A is equal to or a superset of B. @@ -535,6 +718,8 @@ class Qualifiers { // be changed. (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || !other.hasObjCGCAttr()) && + // Pointer-auth qualifiers must match exactly. + PtrAuth == other.PtrAuth && // ObjC lifetime qualifiers must match exactly. getObjCLifetime() == other.getObjCLifetime() && // CVR qualifiers may subset. @@ -567,8 +752,12 @@ class Qualifiers { /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; - bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } - bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } + bool operator==(Qualifiers Other) const { + return Mask == Other.Mask && PtrAuth == Other.PtrAuth; + } + bool operator!=(Qualifiers Other) const { + return Mask != Other.Mask || PtrAuth != Other.PtrAuth; + } explicit operator bool() const { return hasQualifiers(); } @@ -606,6 +795,7 @@ class Qualifiers { void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); + PtrAuth.Profile(ID); } private: @@ -613,6 +803,9 @@ class Qualifiers { // |C R V|U|GCAttr|Lifetime|AddressSpace| uint32_t Mask = 0; + PointerAuthQualifier PtrAuth; + static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t), + "PointerAuthQualifier must be 32 bits"); static const uint32_t UMask = 0x8; static const uint32_t UShift = 3; static const uint32_t GCAttrMask = 0x30; diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h new file mode 100644 index 00000000000000..c69847ac704a41 --- /dev/null +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -0,0 +1,23 @@ +//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines options for configuring pointer-auth technologies +// like ARMv8.3. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H +#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H + +namespace clang { + +constexpr int PointerAuthKeyNone = -1; + +} // end namespace clang + +#endif >From cbfde2159c0af8b472ab296c37dc1adf9fc4ad91 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Thu, 7 Mar 2024 17:54:20 +0300 Subject: [PATCH 4/4] [clang] Support `PointerAuthQualifier` in `QualType` --- clang/include/clang/AST/ASTContext.h | 10 ++++++++++ clang/include/clang/AST/Type.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ff6b64c7f72d57..4fd214592d1f27 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2182,6 +2182,16 @@ class ASTContext : public RefCountedBase<ASTContext> { return getQualifiedType(type.getUnqualifiedType(), Qs); } + /// \brief Return a type with the given __ptrauth qualifier. + QualType getPointerAuthType(QualType type, PointerAuthQualifier pointerAuth) { + assert(!type.getPointerAuth()); + assert(pointerAuth); + + Qualifiers qs; + qs.setPointerAuth(pointerAuth); + return getQualifiedType(type, qs); + } + unsigned char getFixedPointScale(QualType Ty) const; unsigned char getFixedPointIBits(QualType Ty) const; llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 1741a3017f7280..48a51dd851ac36 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1434,6 +1434,10 @@ class QualType { // true when Type is objc's weak and weak is enabled but ARC isn't. bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const; + PointerAuthQualifier getPointerAuth() const { + return getQualifiers().getPointerAuth(); + } + enum PrimitiveDefaultInitializeKind { /// The type does not fall into any of the following categories. Note that /// this case is zero-valued so that values of this enum can be used as a _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits