Skip to content

Commit 71d7760

Browse files
[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 ahmedbougacha@cc7ba7e - ObjC isa signing ahmedbougacha@c9ce0d4 Also applies a fix from access-softek/llvm-project#75 Co-authored-by: Ahmed Bougacha <[email protected]>
1 parent 9e296a1 commit 71d7760

File tree

2 files changed

+227
-11
lines changed

2 files changed

+227
-11
lines changed

clang/include/clang/AST/Type.h

Lines changed: 204 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
#include "clang/Basic/Diagnostic.h"
2626
#include "clang/Basic/ExceptionSpecificationType.h"
2727
#include "clang/Basic/LLVM.h"
28+
#include "clang/Basic/LangOptions.h"
2829
#include "clang/Basic/Linkage.h"
2930
#include "clang/Basic/PartialDiagnostic.h"
31+
#include "clang/Basic/PointerAuthOptions.h"
3032
#include "clang/Basic/SourceLocation.h"
3133
#include "clang/Basic/Specifiers.h"
3234
#include "clang/Basic/Visibility.h"
@@ -138,6 +140,165 @@ using CanQualType = CanQual<Type>;
138140
#define TYPE(Class, Base) class Class##Type;
139141
#include "clang/AST/TypeNodes.inc"
140142

143+
/// Pointer-authentication qualifiers.
144+
class PointerAuthQualifier {
145+
enum : uint32_t {
146+
EnabledShift = 0,
147+
EnabledBits = 1,
148+
EnabledMask = 1 << EnabledShift,
149+
AddressDiscriminatedShift = EnabledShift + EnabledBits,
150+
AddressDiscriminatedBits = 1,
151+
AddressDiscriminatedMask = 1 << AddressDiscriminatedShift,
152+
AuthenticationModeShift =
153+
AddressDiscriminatedShift + AddressDiscriminatedBits,
154+
AuthenticationModeBits = 2,
155+
AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
156+
<< AuthenticationModeShift,
157+
IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
158+
IsaPointerBits = 1,
159+
IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
160+
AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
161+
AuthenticatesNullValuesBits = 1,
162+
AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
163+
<< AuthenticatesNullValuesShift,
164+
KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
165+
KeyBits = 10,
166+
KeyMask = ((1 << KeyBits) - 1) << KeyShift,
167+
DiscriminatorShift = KeyShift + KeyBits,
168+
DiscriminatorBits = 16,
169+
DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift,
170+
};
171+
172+
// bits: |0 |1 |2..3 |4 |
173+
// |Enabled|Address|AuthenticationMode|ISA pointer|
174+
// bits: |5 |6..15| 16...31 |
175+
// |AuthenticatesNull|Key |Discriminator|
176+
uint32_t Data;
177+
178+
static_assert((EnabledBits + AddressDiscriminatedBits +
179+
AuthenticationModeBits + IsaPointerBits +
180+
AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
181+
32,
182+
"PointerAuthQualifier should be exactly 32 bits");
183+
static_assert((EnabledMask + AddressDiscriminatedMask +
184+
AuthenticationModeMask + IsaPointerMask +
185+
AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
186+
0xFFFFFFFF,
187+
"All masks should cover the entire bits");
188+
static_assert((EnabledMask ^ AddressDiscriminatedMask ^
189+
AuthenticationModeMask ^ IsaPointerMask ^
190+
AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
191+
0xFFFFFFFF,
192+
"All masks should cover the entire bits");
193+
194+
PointerAuthQualifier(unsigned key, bool isAddressDiscriminated,
195+
unsigned extraDiscriminator,
196+
PointerAuthenticationMode authenticationMode,
197+
bool isIsaPointer, bool authenticatesNullValues)
198+
: Data(EnabledMask |
199+
(isAddressDiscriminated
200+
? static_cast<uint32_t>(AddressDiscriminatedMask)
201+
: 0) |
202+
(key << KeyShift) |
203+
(unsigned(authenticationMode) << AuthenticationModeShift) |
204+
(extraDiscriminator << DiscriminatorShift) |
205+
(isIsaPointer << IsaPointerShift) |
206+
(authenticatesNullValues << AuthenticatesNullValuesShift)) {
207+
assert(key <= KeyNoneInternal);
208+
assert(extraDiscriminator <= MaxDiscriminator);
209+
}
210+
211+
public:
212+
enum {
213+
KeyNoneInternal = (1u << KeyBits) - 1,
214+
215+
/// The maximum supported pointer-authentication key.
216+
MaxKey = KeyNoneInternal - 1,
217+
218+
/// The maximum supported pointer-authentication discriminator.
219+
MaxDiscriminator = (1u << DiscriminatorBits) - 1
220+
};
221+
222+
public:
223+
PointerAuthQualifier() : Data(0) {}
224+
225+
static PointerAuthQualifier
226+
Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator,
227+
PointerAuthenticationMode authenticationMode, bool isIsaPointer,
228+
bool authenticatesNullValues) {
229+
if (key == PointerAuthKeyNone)
230+
key = KeyNoneInternal;
231+
assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value");
232+
return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator,
233+
authenticationMode, isIsaPointer,
234+
authenticatesNullValues);
235+
}
236+
237+
bool isPresent() const {
238+
return getAuthenticationMode() != PointerAuthenticationMode::None;
239+
}
240+
241+
explicit operator bool() const { return isPresent(); }
242+
243+
unsigned getKey() const {
244+
assert(isPresent());
245+
return (Data & KeyMask) >> KeyShift;
246+
}
247+
248+
bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; }
249+
250+
bool isAddressDiscriminated() const {
251+
assert(isPresent());
252+
return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift;
253+
}
254+
255+
unsigned getExtraDiscriminator() const {
256+
assert(isPresent());
257+
return (Data >> DiscriminatorShift);
258+
}
259+
260+
PointerAuthenticationMode getAuthenticationMode() const {
261+
return PointerAuthenticationMode((Data & AuthenticationModeMask) >>
262+
AuthenticationModeShift);
263+
}
264+
265+
bool isIsaPointer() const {
266+
assert(isPresent());
267+
return (Data & IsaPointerMask) >> IsaPointerShift;
268+
}
269+
270+
bool authenticatesNullValues() const {
271+
assert(isPresent());
272+
return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift;
273+
}
274+
275+
PointerAuthQualifier withoutKeyNone() const {
276+
return hasKeyNone() ? PointerAuthQualifier() : *this;
277+
}
278+
279+
friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
280+
return Lhs.Data == Rhs.Data;
281+
}
282+
friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
283+
return Lhs.Data != Rhs.Data;
284+
}
285+
286+
bool isEquivalent(PointerAuthQualifier Other) const {
287+
return withoutKeyNone() == Other.withoutKeyNone();
288+
}
289+
290+
uint32_t getAsOpaqueValue() const { return Data; }
291+
292+
// Deserialize pointer-auth qualifiers from an opaque representation.
293+
static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) {
294+
PointerAuthQualifier result;
295+
result.Data = opaque;
296+
return result;
297+
}
298+
299+
void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
300+
};
301+
141302
/// The collection of all-type qualifiers we support.
142303
/// Clang supports five independent qualifiers:
143304
/// * C99: const, volatile, and restrict
@@ -193,19 +354,27 @@ class Qualifiers {
193354
FastMask = (1 << FastWidth) - 1
194355
};
195356

357+
Qualifiers() : Mask(0), PtrAuth() {}
358+
196359
/// Returns the common set of qualifiers while removing them from
197360
/// the given sets.
198361
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
362+
Qualifiers Q;
363+
if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) {
364+
Q.setPointerAuth(L.getPointerAuth().withoutKeyNone());
365+
PointerAuthQualifier Empty;
366+
L.setPointerAuth(Empty);
367+
R.setPointerAuth(Empty);
368+
}
369+
199370
// If both are only CVR-qualified, bit operations are sufficient.
200371
if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
201-
Qualifiers Q;
202372
Q.Mask = L.Mask & R.Mask;
203373
L.Mask &= ~Q.Mask;
204374
R.Mask &= ~Q.Mask;
205375
return Q;
206376
}
207377

208-
Qualifiers Q;
209378
unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
210379
Q.addCVRQualifiers(CommonCRV);
211380
L.removeCVRQualifiers(CommonCRV);
@@ -250,15 +419,16 @@ class Qualifiers {
250419
}
251420

252421
// Deserialize qualifiers from an opaque representation.
253-
static Qualifiers fromOpaqueValue(unsigned opaque) {
422+
static Qualifiers fromOpaqueValue(uint64_t opaque) {
254423
Qualifiers Qs;
255-
Qs.Mask = opaque;
424+
Qs.Mask = uint32_t(opaque);
425+
Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32));
256426
return Qs;
257427
}
258428

259429
// Serialize these qualifiers into an opaque representation.
260-
unsigned getAsOpaqueValue() const {
261-
return Mask;
430+
uint64_t getAsOpaqueValue() const {
431+
return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32);
262432
}
263433

264434
bool hasConst() const { return Mask & Const; }
@@ -406,6 +576,10 @@ class Qualifiers {
406576
setAddressSpace(space);
407577
}
408578

579+
PointerAuthQualifier getPointerAuth() const { return PtrAuth; }
580+
void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; }
581+
void removePtrAuth() { PtrAuth = PointerAuthQualifier(); }
582+
409583
// Fast qualifiers are those that can be allocated directly
410584
// on a QualType object.
411585
bool hasFastQualifiers() const { return getFastQualifiers(); }
@@ -428,16 +602,16 @@ class Qualifiers {
428602

429603
/// Return true if the set contains any qualifiers which require an ExtQuals
430604
/// node to be allocated.
431-
bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
605+
bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; }
432606
Qualifiers getNonFastQualifiers() const {
433607
Qualifiers Quals = *this;
434608
Quals.setFastQualifiers(0);
435609
return Quals;
436610
}
437611

438612
/// Return true if the set contains any qualifiers.
439-
bool hasQualifiers() const { return Mask; }
440-
bool empty() const { return !Mask; }
613+
bool hasQualifiers() const { return Mask || PtrAuth; }
614+
bool empty() const { return !hasQualifiers(); }
441615

442616
/// Add the qualifiers from the given set to this set.
443617
void addQualifiers(Qualifiers Q) {
@@ -454,6 +628,9 @@ class Qualifiers {
454628
if (Q.hasObjCLifetime())
455629
addObjCLifetime(Q.getObjCLifetime());
456630
}
631+
632+
if (Q.PtrAuth)
633+
PtrAuth = Q.PtrAuth;
457634
}
458635

459636
/// Remove the qualifiers from the given set from this set.
@@ -471,6 +648,9 @@ class Qualifiers {
471648
if (getAddressSpace() == Q.getAddressSpace())
472649
removeAddressSpace();
473650
}
651+
652+
if (PtrAuth == Q.PtrAuth)
653+
PtrAuth = PointerAuthQualifier();
474654
}
475655

476656
/// Add the qualifiers from the given set to this set, given that
@@ -482,7 +662,10 @@ class Qualifiers {
482662
!hasObjCGCAttr() || !qs.hasObjCGCAttr());
483663
assert(getObjCLifetime() == qs.getObjCLifetime() ||
484664
!hasObjCLifetime() || !qs.hasObjCLifetime());
665+
assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth);
485666
Mask |= qs.Mask;
667+
if (qs.PtrAuth)
668+
PtrAuth = qs.PtrAuth;
486669
}
487670

488671
/// Returns true if address space A is equal to or a superset of B.
@@ -535,6 +718,8 @@ class Qualifiers {
535718
// be changed.
536719
(getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
537720
!other.hasObjCGCAttr()) &&
721+
// Pointer-auth qualifiers must match exactly.
722+
PtrAuth == other.PtrAuth &&
538723
// ObjC lifetime qualifiers must match exactly.
539724
getObjCLifetime() == other.getObjCLifetime() &&
540725
// CVR qualifiers may subset.
@@ -567,8 +752,12 @@ class Qualifiers {
567752
/// another set of qualifiers, not considering qualifier compatibility.
568753
bool isStrictSupersetOf(Qualifiers Other) const;
569754

570-
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
571-
bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
755+
bool operator==(Qualifiers Other) const {
756+
return Mask == Other.Mask && PtrAuth == Other.PtrAuth;
757+
}
758+
bool operator!=(Qualifiers Other) const {
759+
return Mask != Other.Mask || PtrAuth != Other.PtrAuth;
760+
}
572761

573762
explicit operator bool() const { return hasQualifiers(); }
574763

@@ -606,13 +795,17 @@ class Qualifiers {
606795

607796
void Profile(llvm::FoldingSetNodeID &ID) const {
608797
ID.AddInteger(Mask);
798+
PtrAuth.Profile(ID);
609799
}
610800

611801
private:
612802
// bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|
613803
// |C R V|U|GCAttr|Lifetime|AddressSpace|
614804
uint32_t Mask = 0;
615805

806+
PointerAuthQualifier PtrAuth;
807+
static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
808+
"PointerAuthQualifier must be 32 bits");
616809
static const uint32_t UMask = 0x8;
617810
static const uint32_t UShift = 3;
618811
static const uint32_t GCAttrMask = 0x30;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===--- PointerAuthOptions.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+
// This file defines options for configuring pointer-auth technologies
10+
// like ARMv8.3.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
15+
#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
16+
17+
namespace clang {
18+
19+
constexpr int PointerAuthKeyNone = -1;
20+
21+
} // end namespace clang
22+
23+
#endif

0 commit comments

Comments
 (0)