Skip to content

Commit 6bb6300

Browse files
authored
[PAC] Fix address discrimination for type info vtable pointers (#102199)
In #99726, `-fptrauth-type-info-vtable-pointer-discrimination` was introduced, which is intended to enable type and address discrimination for type_info vtable pointers. However, some codegen logic for actually enabling address discrimination was missing. This patch addresses the issue. Fixes #101716
1 parent f225b07 commit 6bb6300

34 files changed

+429
-401
lines changed

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3437,7 +3437,7 @@ class ItaniumRTTIBuilder {
34373437
llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
34383438

34393439
/// BuildVTablePointer - Build the vtable pointer for the given type.
3440-
void BuildVTablePointer(const Type *Ty);
3440+
void BuildVTablePointer(const Type *Ty, llvm::Constant *StorageAddress);
34413441

34423442
/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
34433443
/// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
@@ -3834,7 +3834,8 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
38343834
return true;
38353835
}
38363836

3837-
void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
3837+
void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
3838+
llvm::Constant *StorageAddress) {
38383839
// abi::__class_type_info.
38393840
static const char * const ClassTypeInfo =
38403841
"_ZTVN10__cxxabiv117__class_type_infoE";
@@ -3981,9 +3982,12 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
39813982
VTable, Two);
39823983
}
39833984

3984-
if (auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer)
3985-
VTable = CGM.getConstantSignedPointer(VTable, Schema, nullptr, GlobalDecl(),
3986-
QualType(Ty, 0));
3985+
if (const auto &Schema =
3986+
CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer)
3987+
VTable = CGM.getConstantSignedPointer(
3988+
VTable, Schema,
3989+
Schema.isAddressDiscriminated() ? StorageAddress : nullptr,
3990+
GlobalDecl(), QualType(Ty, 0));
39873991

39883992
Fields.push_back(VTable);
39893993
}
@@ -4099,8 +4103,18 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
40994103
llvm::GlobalVariable::LinkageTypes Linkage,
41004104
llvm::GlobalValue::VisibilityTypes Visibility,
41014105
llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
4106+
SmallString<256> Name;
4107+
llvm::raw_svector_ostream Out(Name);
4108+
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
4109+
llvm::Module &M = CGM.getModule();
4110+
llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
4111+
// int8 is an arbitrary type to be replaced later with replaceInitializer.
4112+
llvm::GlobalVariable *GV =
4113+
new llvm::GlobalVariable(M, CGM.Int8Ty, /*isConstant=*/true, Linkage,
4114+
/*Initializer=*/nullptr, Name);
4115+
41024116
// Add the vtable pointer.
4103-
BuildVTablePointer(cast<Type>(Ty));
4117+
BuildVTablePointer(cast<Type>(Ty), GV);
41044118

41054119
// And the name.
41064120
llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
@@ -4218,16 +4232,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
42184232
llvm_unreachable("HLSL doesn't support RTTI");
42194233
}
42204234

4221-
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
4222-
4223-
SmallString<256> Name;
4224-
llvm::raw_svector_ostream Out(Name);
4225-
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
4226-
llvm::Module &M = CGM.getModule();
4227-
llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
4228-
llvm::GlobalVariable *GV =
4229-
new llvm::GlobalVariable(M, Init->getType(),
4230-
/*isConstant=*/true, Linkage, Init, Name);
4235+
GV->replaceInitializer(llvm::ConstantStruct::getAnon(Fields));
42314236

42324237
// Export the typeinfo in the same circumstances as the vtable is exported.
42334238
auto GVDLLStorageClass = DLLStorageClass;

clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm -fhalf-no-semantic-interposition | FileCheck %s
55

66
// The inline function is emitted in each module with the same comdat
7-
// CHECK: $_ZTS1A = comdat any
87
// CHECK: $_ZTI1A = comdat any
8+
// CHECK: $_ZTS1A = comdat any
99
// CHECK: $_ZTI1B.rtti_proxy = comdat any
1010

1111
// The VTable is emitted everywhere used

clang/test/CodeGenCXX/RelativeVTablesABI/inlined-key-function.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm | FileCheck %s
55

66
// CHECK: $_ZTV1A = comdat any
7-
// CHECK: $_ZTS1A = comdat any
87
// CHECK: $_ZTI1A = comdat any
8+
// CHECK: $_ZTS1A = comdat any
99
// CHECK: $_ZTI1A.rtti_proxy = comdat any
1010

1111
// The VTable is linkonce_odr and in a comdat here bc it’s key function is inline defined.

clang/test/CodeGenCXX/RelativeVTablesABI/parent-and-child-in-comdats.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
// CHECK: $_ZN1A3fooEv = comdat any
99
// CHECK: $_ZN1B3fooEv = comdat any
1010
// CHECK: $_ZTV1A = comdat any
11-
// CHECK: $_ZTS1A = comdat any
1211
// CHECK: $_ZTI1A = comdat any
12+
// CHECK: $_ZTS1A = comdat any
1313
// CHECK: $_ZTI1A.rtti_proxy = comdat any
1414
// CHECK: $_ZTV1B = comdat any
15-
// CHECK: $_ZTS1B = comdat any
1615
// CHECK: $_ZTI1B = comdat any
16+
// CHECK: $_ZTS1B = comdat any
1717
// CHECK: $_ZTI1B.rtti_proxy = comdat any
1818

1919
// Both the vtables for A and B are emitted and in their own comdats.

clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
// A::foo() has a comdat since it is an inline function
88
// CHECK: $_ZN1A3fooEv = comdat any
99
// CHECK: $_ZTV1A = comdat any
10+
// CHECK: $_ZTI1A = comdat any
1011
// CHECK: $_ZTS1A = comdat any
1112

1213
// The VTable for A has its own comdat section bc it has no key function
13-
// CHECK: $_ZTI1A = comdat any
1414
// CHECK: $_ZTI1A.rtti_proxy = comdat any
1515

1616
// The VTable for A is emitted here and in a comdat section since it has no key function, and is used in this module when creating an instance of A.
1717
// CHECK: @_ZTV1A.local = linkonce_odr hidden unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, comdat($_ZTV1A), align 4
18+
// CHECK: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, comdat, align 8
1819
// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
1920
// CHECK: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat, align 1
20-
// CHECK: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, comdat, align 8
2121
// CHECK: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, comdat
2222
// CHECK: @_ZTV1A = linkonce_odr unnamed_addr alias { [3 x i32] }, ptr @_ZTV1A.local
2323

clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
// The vtable definition itself is private so we can take relative references to
1010
// it. The vtable symbol will be exposed through a public alias.
1111
// CHECK: @_ZTV1A.local = internal unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4
12+
// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8
1213
// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
1314
// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
14-
// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8
1515

1616
// The rtti should be in a comdat
1717
// CHECK: @_ZTI1A.rtti_proxy = {{.*}}comdat

clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
// CHECK: $_ZTI1A.rtti_proxy = comdat any
66
// CHECK: $_ZTI1B.rtti_proxy = comdat any
77

8+
// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8
89
// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
910
// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
10-
// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8
11+
// CHECK: @_ZTI1B ={{.*}} constant { ptr, ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 8), ptr @_ZTS1B, ptr @_ZTI1A }, align 8
1112
// CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global [0 x ptr]
1213
// CHECK: @_ZTS1B ={{.*}} constant [3 x i8] c"1B\00", align 1
13-
// CHECK: @_ZTI1B ={{.*}} constant { ptr, ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 8), ptr @_ZTS1B, ptr @_ZTI1A }, align 8
1414
// CHECK: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, comdat
1515
// CHECK: @_ZTI1B.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1B, comdat
1616

clang/test/CodeGenCXX/armv7k.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,17 @@ namespace test2 {
5050

5151
struct __attribute__((visibility("hidden"))) B {};
5252
const std::type_info &b0 = typeid(B);
53-
// CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant
5453
// CHECK-GLOBALS: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, ptr @_ZTSN5test21BE }
54+
// CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant
5555

5656
const std::type_info &b1 = typeid(B*);
57-
// CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant
5857
// CHECK-GLOBALS: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, ptr @_ZTSPN5test21BE, i32 0, ptr @_ZTIN5test21BE
58+
// CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant
5959

6060
struct C {};
6161
const std::type_info &c0 = typeid(C);
62-
// CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr constant [11 x i8] c"N5test21CE\00"
6362
// CHECK-GLOBALS: @_ZTIN5test21CE = linkonce_odr constant { {{.*}}, ptr @_ZTSN5test21CE }
63+
// CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr constant [11 x i8] c"N5test21CE\00"
6464
}
6565

6666
// va_list should be based on "char *" rather than "ptr".

clang/test/CodeGenCXX/dynamic-cast-address-space.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ B fail;
1010
// CHECK: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8
1111
// CHECK: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8
1212
// CHECK: @_ZTI1A = external addrspace(1) constant ptr addrspace(1)
13+
// CHECK: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8
1314
// CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)]
1415
// CHECK: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1
15-
// CHECK: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8
1616
// CHECK: @__oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 500
1717
//.
1818
// WITH-NONZERO-DEFAULT-AS: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8
1919
// WITH-NONZERO-DEFAULT-AS: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8
2020
// WITH-NONZERO-DEFAULT-AS: @_ZTI1A = external addrspace(1) constant ptr addrspace(1)
21+
// WITH-NONZERO-DEFAULT-AS: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8
2122
// WITH-NONZERO-DEFAULT-AS: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)]
2223
// WITH-NONZERO-DEFAULT-AS: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1
23-
// WITH-NONZERO-DEFAULT-AS: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8
2424
//.
2525
// CHECK-LABEL: define dso_local noundef nonnull align 8 dereferenceable(8) ptr @_Z1fP1A(
2626
// CHECK-SAME: ptr noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 {

clang/test/CodeGenCXX/exceptions-no-rtti.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// CHECK: @_ZTIN5test11AE = linkonce_odr constant
44
// CHECK: @_ZTIN5test11BE = linkonce_odr constant
55
// CHECK: @_ZTIN5test11CE = linkonce_odr constant
6-
// CHECK: @_ZTIN5test11DE = linkonce_odr constant
76
// CHECK: @_ZTIPN5test11DE = linkonce_odr constant {{.*}} @_ZTIN5test11DE
7+
// CHECK: @_ZTIN5test11DE = linkonce_odr constant
88

99
// PR6974: this shouldn't crash
1010
namespace test0 {

clang/test/CodeGenCXX/implicit-record-visibility.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
// under -fvisibility=hidden the type of function f, due to its va_list (aka
88
// __builtin_va_list, aka __va_list_tag (*)[1]) parameter would be hidden:
99

10-
// CHECK: @_ZTSFvP13__va_list_tagE = linkonce_odr constant
1110
// CHECK: @_ZTIFvP13__va_list_tagE = linkonce_odr constant
11+
// CHECK: @_ZTSFvP13__va_list_tagE = linkonce_odr constant
1212
void f(va_list) { (void)typeid(f); }

0 commit comments

Comments
 (0)