Skip to content

Commit 61be7a9

Browse files
[clang] Define ptrauth_string_discriminator builtin.
This exposes the ABI-stable hash function that allows computing a 16-bit discriminator from a constant string. This allows manually matching the implicit string discriminators computed in the ABI (e.g., from mangled names for vtable pointer/entry signing), as well as enabling the use of interesting discriminators when manually annotating specific pointers with the __ptrauth qualifier. Co-Authored-By: John McCall <[email protected]>
1 parent 42cb73f commit 61be7a9

File tree

7 files changed

+70
-0
lines changed

7 files changed

+70
-0
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4411,6 +4411,12 @@ def PtrauthAuth : Builtin {
44114411
let Prototype = "void*(void*,int,void*)";
44124412
}
44134413

4414+
def PtrauthStringDiscriminator : Builtin {
4415+
let Spellings = ["__builtin_ptrauth_string_discriminator"];
4416+
let Attributes = [NoThrow, Const, Constexpr];
4417+
let Prototype = "size_t(char const*)";
4418+
}
4419+
44144420
// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
44154421
// We need the generic prototype, since the packet type could be anything.
44164422
def ReadPipe : OCLPipeLangBuiltin {

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,8 @@ def warn_ptrauth_sign_null_pointer :
928928
def warn_ptrauth_auth_null_pointer :
929929
Warning<"authenticating a null pointer will almost certainly trap">,
930930
InGroup<PtrAuthNullPointers>;
931+
def err_ptrauth_string_not_literal : Error<
932+
"argument must be a string literal%select{| of char type}0">;
931933

932934
/// main()
933935
// static main() is not an error in C, just in C++.

clang/lib/AST/ExprConstant.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "llvm/ADT/StringExtras.h"
5959
#include "llvm/Support/Debug.h"
6060
#include "llvm/Support/SaveAndRestore.h"
61+
#include "llvm/Support/SipHash.h"
6162
#include "llvm/Support/TimeProfiler.h"
6263
#include "llvm/Support/raw_ostream.h"
6364
#include <cstring>
@@ -12583,6 +12584,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1258312584
case Builtin::BI__builtin_expect_with_probability:
1258412585
return Visit(E->getArg(0));
1258512586

12587+
case Builtin::BI__builtin_ptrauth_string_discriminator: {
12588+
auto literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts());
12589+
auto result = getPointerAuthStableSipHash16(literal->getString());
12590+
return Success(result, E);
12591+
}
12592+
1258612593
case Builtin::BI__builtin_ffs:
1258712594
case Builtin::BI__builtin_ffsl:
1258812595
case Builtin::BI__builtin_ffsll: {

clang/lib/Headers/ptrauth.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,17 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
135135
#define ptrauth_auth_data(__value, __old_key, __old_data) \
136136
__builtin_ptrauth_auth(__value, __old_key, __old_data)
137137

138+
/* Compute a constant discriminator from the given string.
139+
140+
The result can be used as the second argument to
141+
ptrauth_blend_discriminator or the third argument to the
142+
__ptrauth qualifier. It has type size_t.
143+
144+
The argument must be a string literal.
145+
A call to this function is an integer constant expression. */
146+
#define ptrauth_string_discriminator(__string) \
147+
__builtin_ptrauth_string_discriminator(__string)
148+
138149
/* Compute a signature for the given pair of pointer-sized values.
139150
The order of the arguments is significant.
140151
@@ -196,6 +207,12 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
196207
__value; \
197208
})
198209

210+
#define ptrauth_string_discriminator(__string) \
211+
({ \
212+
(void)__string; \
213+
((ptrauth_extra_data_t)0); \
214+
})
215+
199216
#define ptrauth_sign_generic_data(__value, __data) \
200217
({ \
201218
(void)__value; \

clang/lib/Sema/SemaChecking.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,24 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) {
21562156
return Call;
21572157
}
21582158

2159+
static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *call) {
2160+
if (checkPointerAuthEnabled(S, call)) return ExprError();
2161+
2162+
// We've already performed normal call type-checking.
2163+
Expr *arg = call->getArgs()[0]->IgnoreParenImpCasts();
2164+
2165+
// Operand must be an ordinary or UTF-8 string literal.
2166+
auto literal = dyn_cast<StringLiteral>(arg);
2167+
if (!literal || literal->getCharByteWidth() != 1) {
2168+
S.Diag(arg->getExprLoc(), diag::err_ptrauth_string_not_literal)
2169+
<< (literal ? 1 : 0)
2170+
<< arg->getSourceRange();
2171+
return ExprError();
2172+
}
2173+
2174+
return call;
2175+
}
2176+
21592177
static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall) {
21602178
if (S.checkArgCount(TheCall, 1))
21612179
return ExprError();
@@ -2922,6 +2940,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
29222940
return PointerAuthSignGenericData(*this, TheCall);
29232941
case Builtin::BI__builtin_ptrauth_auth_and_resign:
29242942
return PointerAuthAuthAndResign(*this, TheCall);
2943+
case Builtin::BI__builtin_ptrauth_string_discriminator:
2944+
return PointerAuthStringDiscriminator(*this, TheCall);
29252945
// OpenCL v2.0, s6.13.16 - Pipe functions
29262946
case Builtin::BIread_pipe:
29272947
case Builtin::BIwrite_pipe:

clang/test/CodeGen/ptrauth-intrinsics.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,16 @@ void test_sign_generic_data() {
7171
// CHECK-NEXT: store i64 [[RESULT]], ptr @signature,
7272
signature = __builtin_ptrauth_sign_generic_data(fnptr, ptr_discriminator);
7373
}
74+
75+
// CHECK-LABEL: define void @test_string_discriminator()
76+
void test_string_discriminator() {
77+
// CHECK: [[X:%.*]] = alloca i32
78+
79+
// Check a couple of random discriminators used by Swift.
80+
81+
// CHECK: store i32 58298, ptr [[X]],
82+
int x = __builtin_ptrauth_string_discriminator("InitializeWithCopy");
83+
84+
// CHECK: store i32 9112, ptr [[X]],
85+
x = __builtin_ptrauth_string_discriminator("DestroyArray");
86+
}

clang/test/Sema/ptrauth-intrinsics-macro.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,8 @@ void test(int *dp, int value) {
3232
int t2 = ptrauth_sign_generic_data(dp, 0);
3333
(void)t2;
3434
}
35+
36+
void test_string_discriminator(int *dp) {
37+
ptrauth_extra_data_t t0 = ptrauth_string_discriminator("string");
38+
(void)t0;
39+
}

0 commit comments

Comments
 (0)