Skip to content

Commit 45e5b93

Browse files
committed
Implement mangling/demangling __ptrauth on Windows
Add mangling/demangling tests.
1 parent 9cbf8b0 commit 45e5b93

File tree

9 files changed

+143
-2
lines changed

9 files changed

+143
-2
lines changed

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ class MicrosoftCXXNameMangler {
430430
void mangleRefQualifier(RefQualifierKind RefQualifier);
431431
void manglePointerCVQualifiers(Qualifiers Quals);
432432
void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType);
433+
void manglePointerAuthQualifier(Qualifiers Quals);
433434

434435
void mangleUnscopedTemplateName(GlobalDecl GD);
435436
void
@@ -2334,6 +2335,17 @@ void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
23342335
Out << 'F';
23352336
}
23362337

2338+
void MicrosoftCXXNameMangler::manglePointerAuthQualifier(Qualifiers Quals) {
2339+
PointerAuthQualifier PointerAuth = Quals.getPointerAuth();
2340+
if (!PointerAuth)
2341+
return;
2342+
2343+
Out << "__ptrauth";
2344+
mangleNumber(PointerAuth.getKey());
2345+
mangleNumber(PointerAuth.isAddressDiscriminated());
2346+
mangleNumber(PointerAuth.getExtraDiscriminator());
2347+
}
2348+
23372349
void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) {
23382350
// <pointer-cv-qualifiers> ::= P # no qualifiers
23392351
// ::= Q # const
@@ -3366,6 +3378,7 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
33663378
QualType PointeeType = T->getPointeeType();
33673379
manglePointerCVQualifiers(Quals);
33683380
manglePointerExtQualifiers(Quals, PointeeType);
3381+
manglePointerAuthQualifier(Quals);
33693382

33703383
// For pointer size address spaces, go down the same type mangling path as
33713384
// non address space types.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=arm64-apple-ios %s | FileCheck %s
2+
// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=aarch64-linux-gnu %s | FileCheck %s
3+
4+
// CHECK: define {{.*}}void @_Z3fooPU9__ptrauthILj3ELb1ELj234EEPi(
5+
void foo(int * __ptrauth(3, 1, 234) *) {}
6+
7+
template <class T>
8+
void foo(T t) {}
9+
10+
// CHECK: define weak_odr void @_Z3fooIPU9__ptrauthILj1ELb0ELj64EEPiEvT_(
11+
template void foo<int * __ptrauth(1, 0, 64) *>(int * __ptrauth(1, 0, 64) *);
12+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=aarch64-windows-msvc %s | FileCheck %s
2+
3+
template <class T>
4+
struct S {};
5+
6+
// CHECK: @"?s@@3U?$S@PE__ptrauth1A@ENC@AH@@A" =
7+
S<int * __ptrauth(2, 0, 1234)> s;
8+
9+
// CHECK: define dso_local void @"?foo@@YAXPEAPE__ptrauth20OK@AH@Z"(
10+
void foo(int * __ptrauth(3, 1, 234) *) {}
11+
12+
template <class T>
13+
void foo(T t) {}
14+
15+
// CHECK: define weak_odr dso_local void @"??$foo@PEAPE__ptrauth0A@EA@AH@@YAXPEAPE__ptrauth0A@EA@AH@Z"(
16+
template void foo<int * __ptrauth(1, 0, 64) *>(int * __ptrauth(1, 0, 64) *);
17+

libcxxabi/test/test_demangle.pass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30247,6 +30247,9 @@ const char* cases[][2] = {
3024730247
{"_Z1fDSDRm", "f(_Sat unsigned long _Fract)"},
3024830248

3024930249
{"_Z11bfloat16addDF16bDF16b", "bfloat16add(std::bfloat16_t, std::bfloat16_t)"},
30250+
30251+
{"_Z3fooPU9__ptrauthILj3ELb1ELj234EEPi", "foo(int* __ptrauth<3u, true, 234u>*)"},
30252+
{"_Z3fooIPU9__ptrauthILj1ELb0ELj64EEPiEvT_", "void foo<int* __ptrauth<1u, false, 64u>*>(int* __ptrauth<1u, false, 64u>*)"},
3025030253
// clang-format on
3025130254
};
3025230255

llvm/include/llvm/Demangle/MicrosoftDemangle.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ class Demangler {
173173

174174
Qualifiers demanglePointerExtQualifiers(std::string_view &MangledName);
175175

176+
bool isMemberPointer(std::string_view MangledName, bool &Error);
177+
178+
std::optional<PointerAuthQualifierNode::ArgArray>
179+
demanglePointerAuthQualifier(std::string_view &MangledName);
180+
181+
PointerAuthQualifierNode *
182+
createPointerAuthQualifier(std::string_view &MangledName);
183+
176184
// Parser functions. This is a recursive-descent parser.
177185
TypeNode *demangleType(std::string_view &MangledName,
178186
QualifierMangleMode QMM);

llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ enum class NodeKind {
253253
LocalStaticGuardVariable,
254254
FunctionSymbol,
255255
VariableSymbol,
256-
SpecialTableSymbol
256+
SpecialTableSymbol,
257+
PointerAuthQualifier,
257258
};
258259

259260
struct Node {
@@ -295,6 +296,7 @@ struct SymbolNode;
295296
struct FunctionSymbolNode;
296297
struct VariableSymbolNode;
297298
struct SpecialTableSymbolNode;
299+
struct PointerAuthQualifierNode;
298300

299301
struct TypeNode : public Node {
300302
explicit TypeNode(NodeKind K) : Node(K) {}
@@ -467,6 +469,8 @@ struct PointerTypeNode : public TypeNode {
467469
// If this is a member pointer, this is the class that the member is in.
468470
QualifiedNameNode *ClassParent = nullptr;
469471

472+
PointerAuthQualifierNode *PointerAuthQualifier = nullptr;
473+
470474
// Represents a type X in "a pointer to X", "a reference to X", or
471475
// "rvalue-reference to X"
472476
TypeNode *Pointee = nullptr;
@@ -625,6 +629,22 @@ struct FunctionSymbolNode : public SymbolNode {
625629
FunctionSignatureNode *Signature = nullptr;
626630
};
627631

632+
struct PointerAuthQualifierNode : public Node {
633+
PointerAuthQualifierNode() : Node(NodeKind::PointerAuthQualifier) {}
634+
635+
// __ptrauth takes three arguments:
636+
// - key
637+
// - isAddressDiscriminated
638+
// - extra discriminator
639+
static constexpr unsigned NumArgs = 3;
640+
typedef std::array<uint64_t, NumArgs> ArgArray;
641+
642+
void output(OutputBuffer &OB, OutputFlags Flags) const override;
643+
644+
// List of arguments.
645+
NodeArrayNode *Components = nullptr;
646+
};
647+
628648
} // namespace ms_demangle
629649
} // namespace llvm
630650

llvm/lib/Demangle/MicrosoftDemangle.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static bool startsWith(std::string_view S, std::string_view PrefixA,
6666
return llvm::itanium_demangle::starts_with(S, Prefix);
6767
}
6868

69-
static bool isMemberPointer(std::string_view MangledName, bool &Error) {
69+
bool Demangler::isMemberPointer(std::string_view MangledName, bool &Error) {
7070
Error = false;
7171
const char F = MangledName.front();
7272
MangledName.remove_prefix(1);
@@ -107,6 +107,7 @@ static bool isMemberPointer(std::string_view MangledName, bool &Error) {
107107
consumeFront(MangledName, 'E'); // 64-bit
108108
consumeFront(MangledName, 'I'); // restrict
109109
consumeFront(MangledName, 'F'); // unaligned
110+
demanglePointerAuthQualifier(MangledName);
110111

111112
if (MangledName.empty()) {
112113
Error = true;
@@ -2094,6 +2095,8 @@ PointerTypeNode *Demangler::demanglePointerType(std::string_view &MangledName) {
20942095
Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
20952096
Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
20962097

2098+
Pointer->PointerAuthQualifier = createPointerAuthQualifier(MangledName);
2099+
20972100
Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle);
20982101
return Pointer;
20992102
}
@@ -2142,6 +2145,49 @@ Demangler::demanglePointerExtQualifiers(std::string_view &MangledName) {
21422145
return Quals;
21432146
}
21442147

2148+
std::optional<PointerAuthQualifierNode::ArgArray>
2149+
Demangler::demanglePointerAuthQualifier(std::string_view &MangledName) {
2150+
if (!consumeFront(MangledName, "__ptrauth"))
2151+
return std::nullopt;
2152+
2153+
constexpr unsigned NumArgs = PointerAuthQualifierNode::NumArgs;
2154+
PointerAuthQualifierNode::ArgArray Array;
2155+
2156+
for (unsigned I = 0; I < NumArgs; ++I) {
2157+
bool IsNegative = false;
2158+
uint64_t Value = 0;
2159+
std::tie(Value, IsNegative) = demangleNumber(MangledName);
2160+
if (IsNegative)
2161+
return std::nullopt;
2162+
2163+
Array[I] = Value;
2164+
}
2165+
2166+
return Array;
2167+
}
2168+
2169+
PointerAuthQualifierNode *
2170+
Demangler::createPointerAuthQualifier(std::string_view &MangledName) {
2171+
constexpr unsigned NumArgs = PointerAuthQualifierNode::NumArgs;
2172+
std::optional<PointerAuthQualifierNode::ArgArray> Vals =
2173+
demanglePointerAuthQualifier(MangledName);
2174+
2175+
if (!Vals)
2176+
return nullptr;
2177+
2178+
PointerAuthQualifierNode *PtrAuthQual =
2179+
Arena.alloc<PointerAuthQualifierNode>();
2180+
NodeArrayNode *Array = Arena.alloc<NodeArrayNode>();
2181+
PtrAuthQual->Components = Array;
2182+
Array->Count = NumArgs;
2183+
Array->Nodes = Arena.allocArray<Node *>(NumArgs);
2184+
2185+
for (unsigned I = 0; I < NumArgs; ++I)
2186+
Array->Nodes[I] = Arena.alloc<IntegerLiteralNode>((*Vals)[I], false);
2187+
2188+
return PtrAuthQual;
2189+
}
2190+
21452191
ArrayTypeNode *Demangler::demangleArrayType(std::string_view &MangledName) {
21462192
assert(MangledName.front() == 'Y');
21472193
MangledName.remove_prefix(1);

llvm/lib/Demangle/MicrosoftDemangleNodes.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,9 @@ void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
521521
assert(false);
522522
}
523523
outputQualifiers(OB, Quals, false, false);
524+
525+
if (PointerAuthQualifier)
526+
PointerAuthQualifier->output(OB, Flags);
524527
}
525528

526529
void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
@@ -591,6 +594,13 @@ void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
591594
Signature->outputPost(OB, Flags);
592595
}
593596

597+
void PointerAuthQualifierNode::output(OutputBuffer &OB,
598+
OutputFlags Flags) const {
599+
OB << "__ptrauth(";
600+
Components->output(OB, Flags);
601+
OB << ")";
602+
}
603+
594604
void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
595605
const char *AccessSpec = nullptr;
596606
bool IsStatic = true;

llvm/test/Demangle/ms-ptrauth.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; RUN: llvm-undname < %s | FileCheck %s
2+
3+
; CHECK-NOT: Invalid mangled name
4+
5+
?s@@3U?$S@PE__ptrauth1A@ENC@AH@@A
6+
; CHECK: struct S<int *__ptrauth(2, 0, 1234)> s
7+
8+
?foo@@YAXPEAPE__ptrauth20OK@AH@Z
9+
; CHECK: void __cdecl foo(int *__ptrauth(3, 1, 234)*)
10+
11+
??$foo@PEAPE__ptrauth0A@EA@AH@@YAXPEAPE__ptrauth0A@EA@AH@Z
12+
; CHECK: void __cdecl foo<int *__ptrauth(1, 0, 64)*>(int *__ptrauth(1, 0, 64)*)

0 commit comments

Comments
 (0)