Skip to content

Commit 1358f5a

Browse files
committed
fixup! address reviewer comments
Created using spr 1.3.8-beta.1
2 parents 7f70661 + 22570af commit 1358f5a

File tree

20 files changed

+207
-173
lines changed

20 files changed

+207
-173
lines changed

clang/docs/AllocToken.rst

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@ Token Assignment Mode
3131

3232
The default mode to calculate tokens is:
3333

34-
* *TypeHashPointerSplit* (mode=3): This mode assigns a token ID based on
35-
the hash of the allocated type's name, where the top half ID-space is
36-
reserved for types that contain pointers and the bottom half for types that
37-
do not contain pointers.
34+
* ``typehashpointersplit``: This mode assigns a token ID based on the hash of
35+
the allocated type's name, where the top half ID-space is reserved for types
36+
that contain pointers and the bottom half for types that do not contain
37+
pointers.
3838

3939
Other token ID assignment modes are supported, but they may be subject to
4040
change or removal. These may (experimentally) be selected with ``-mllvm
4141
-alloc-token-mode=<mode>``:
4242

43-
* *TypeHash* (mode=2): This mode assigns a token ID based on the hash of
44-
the allocated type's name.
43+
* ``typehash``: This mode assigns a token ID based on the hash of the allocated
44+
type's name.
4545

46-
* *Random* (mode=1): This mode assigns a statically-determined random token ID
47-
to each allocation site.
46+
* ``random``: This mode assigns a statically-determined random token ID to each
47+
allocation site.
4848

49-
* *Increment* (mode=0): This mode assigns a simple, incrementally increasing
50-
token ID to each allocation site.
49+
* ``increment``: This mode assigns a simple, incrementally increasing token ID
50+
to each allocation site.
5151

5252
Allocation Token Instrumentation
5353
================================
@@ -74,7 +74,7 @@ In addition, it is typically recommended to configure the following:
7474

7575
* ``-falloc-token-max=<N>``
7676
Configures the maximum number of tokens. No max by default (tokens bounded
77-
by ``UINT64_MAX``).
77+
by ``SIZE_MAX``).
7878

7979
.. code-block:: console
8080
@@ -85,21 +85,21 @@ Runtime Interface
8585

8686
A compatible runtime must be provided that implements the token-enabled
8787
allocation functions. The instrumentation generates calls to functions that
88-
take a final ``uint64_t token_id`` argument.
88+
take a final ``size_t token_id`` argument.
8989

9090
.. code-block:: c
9191
9292
// C standard library functions
93-
void *__alloc_token_malloc(size_t size, uint64_t token_id);
94-
void *__alloc_token_calloc(size_t count, size_t size, uint64_t token_id);
95-
void *__alloc_token_realloc(void *ptr, size_t size, uint64_t token_id);
93+
void *__alloc_token_malloc(size_t size, size_t token_id);
94+
void *__alloc_token_calloc(size_t count, size_t size, size_t token_id);
95+
void *__alloc_token_realloc(void *ptr, size_t size, size_t token_id);
9696
// ...
9797
9898
// C++ operators (mangled names)
99-
// operator new(size_t, uint64_t)
100-
void *__alloc_token_Znwm(size_t size, uint64_t token_id);
101-
// operator new[](size_t, uint64_t)
102-
void *__alloc_token_Znam(size_t size, uint64_t token_id);
99+
// operator new(size_t, size_t)
100+
void *__alloc_token_Znwm(size_t size, size_t token_id);
101+
// operator new[](size_t, size_t)
102+
void *__alloc_token_Znam(size_t size, size_t token_id);
103103
// ... other variants like nothrow, etc., are also instrumented.
104104
105105
Fast ABI

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class SanitizerArgs {
7474
bool HwasanUseAliases = false;
7575
llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
7676
llvm::AsanDetectStackUseAfterReturnMode::Invalid;
77+
7778
std::string MemtagMode;
7879
bool AllocTokenFastABI = false;
7980
bool AllocTokenExtended = false;

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,8 +1272,58 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
12721272
EmitCheck(std::make_pair(Check, CheckKind), CheckHandler, StaticData, Index);
12731273
}
12741274

1275-
void CodeGenFunction::EmitAllocTokenHint(llvm::CallBase *CB,
1276-
QualType AllocType) {
1275+
static bool
1276+
typeContainsPointer(QualType T,
1277+
llvm::SmallPtrSet<const RecordDecl *, 4> &VisitedRD,
1278+
bool &IncompleteType) {
1279+
QualType CanonicalType = T.getCanonicalType();
1280+
if (CanonicalType->isPointerType())
1281+
return true; // base case
1282+
1283+
// Look through typedef chain to check for special types.
1284+
for (QualType CurrentT = T; const auto *TT = CurrentT->getAs<TypedefType>();
1285+
CurrentT = TT->getDecl()->getUnderlyingType()) {
1286+
const IdentifierInfo *II = TT->getDecl()->getIdentifier();
1287+
if (!II)
1288+
continue;
1289+
// Special Case: Syntactically uintptr_t is not a pointer; semantically,
1290+
// however, very likely used as such. Therefore, classify uintptr_t as a
1291+
// pointer, too.
1292+
if (II->isStr("uintptr_t"))
1293+
return true;
1294+
}
1295+
1296+
// The type is an array; check the element type.
1297+
if (const ArrayType *AT = CanonicalType->getAsArrayTypeUnsafe())
1298+
return typeContainsPointer(AT->getElementType(), VisitedRD, IncompleteType);
1299+
// The type is a struct, class, or union.
1300+
if (const RecordDecl *RD = CanonicalType->getAsRecordDecl()) {
1301+
if (!RD->isCompleteDefinition()) {
1302+
IncompleteType = true;
1303+
return false;
1304+
}
1305+
if (!VisitedRD.insert(RD).second)
1306+
return false; // already visited
1307+
// Check all fields.
1308+
for (const FieldDecl *Field : RD->fields()) {
1309+
if (typeContainsPointer(Field->getType(), VisitedRD, IncompleteType))
1310+
return true;
1311+
}
1312+
// For C++ classes, also check base classes.
1313+
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
1314+
// Polymorphic types require a vptr.
1315+
if (CXXRD->isPolymorphic())
1316+
return true;
1317+
for (const CXXBaseSpecifier &Base : CXXRD->bases()) {
1318+
if (typeContainsPointer(Base.getType(), VisitedRD, IncompleteType))
1319+
return true;
1320+
}
1321+
}
1322+
}
1323+
return false;
1324+
}
1325+
1326+
void CodeGenFunction::EmitAllocToken(llvm::CallBase *CB, QualType AllocType) {
12771327
assert(SanOpts.has(SanitizerKind::AllocToken) &&
12781328
"Only needed with -fsanitize=alloc-token");
12791329

@@ -1290,54 +1340,8 @@ void CodeGenFunction::EmitAllocTokenHint(llvm::CallBase *CB,
12901340
// recursively check if a type contains a pointer type.
12911341
llvm::SmallPtrSet<const RecordDecl *, 4> VisitedRD;
12921342
bool IncompleteType = false;
1293-
auto TypeContainsPtr = [&](auto &&self, QualType T) -> bool {
1294-
QualType CanonicalType = T.getCanonicalType();
1295-
if (CanonicalType->isPointerType())
1296-
return true; // base case
1297-
1298-
// Look through typedef chain to check for special types.
1299-
for (QualType CurrentT = T; const auto *TT = CurrentT->getAs<TypedefType>();
1300-
CurrentT = TT->getDecl()->getUnderlyingType()) {
1301-
const IdentifierInfo *II = TT->getDecl()->getIdentifier();
1302-
if (!II)
1303-
continue;
1304-
// Special Case: Syntactically uintptr_t is not a pointer; semantically,
1305-
// however, very likely used as such. Therefore, classify uintptr_t as a
1306-
// pointer, too.
1307-
if (II->isStr("uintptr_t"))
1308-
return true;
1309-
}
1310-
1311-
// The type is an array; check the element type.
1312-
if (const ArrayType *AT = CanonicalType->getAsArrayTypeUnsafe())
1313-
return self(self, AT->getElementType());
1314-
// The type is a struct, class, or union.
1315-
if (const RecordDecl *RD = CanonicalType->getAsRecordDecl()) {
1316-
if (!RD->isCompleteDefinition()) {
1317-
IncompleteType = true;
1318-
return false;
1319-
}
1320-
if (!VisitedRD.insert(RD).second)
1321-
return false; // already visited
1322-
// Check all fields.
1323-
for (const FieldDecl *Field : RD->fields()) {
1324-
if (self(self, Field->getType()))
1325-
return true;
1326-
}
1327-
// For C++ classes, also check base classes.
1328-
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
1329-
// Polymorphic types require a vptr.
1330-
if (CXXRD->isPolymorphic())
1331-
return true;
1332-
for (const CXXBaseSpecifier &Base : CXXRD->bases()) {
1333-
if (self(self, Base.getType()))
1334-
return true;
1335-
}
1336-
}
1337-
}
1338-
return false;
1339-
};
1340-
const bool ContainsPtr = TypeContainsPtr(TypeContainsPtr, AllocType);
1343+
const bool ContainsPtr =
1344+
typeContainsPointer(AllocType, VisitedRD, IncompleteType);
13411345
if (!ContainsPtr && IncompleteType)
13421346
return;
13431347
auto *ContainsPtrC = Builder.getInt1(ContainsPtr);
@@ -1346,7 +1350,7 @@ void CodeGenFunction::EmitAllocTokenHint(llvm::CallBase *CB,
13461350
// Format: !{<type-name>, <contains-pointer>}
13471351
auto *MDN =
13481352
llvm::MDNode::get(CGM.getLLVMContext(), {TypeNameMD, ContainsPtrMD});
1349-
CB->setMetadata(llvm::LLVMContext::MD_alloc_token_hint, MDN);
1353+
CB->setMetadata(llvm::LLVMContext::MD_alloc_token, MDN);
13501354
}
13511355

13521356
CodeGenFunction::ComplexPairTy CodeGenFunction::

clang/lib/CodeGen/CGExprCXX.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,8 +1713,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
17131713
CGDI->addHeapAllocSiteMetadata(newCall, allocType, E->getExprLoc());
17141714
}
17151715
if (SanOpts.has(SanitizerKind::AllocToken)) {
1716-
// Set !alloc_token_hint metadata.
1717-
EmitAllocTokenHint(newCall, allocType);
1716+
// Set !alloc_token metadata.
1717+
EmitAllocToken(newCall, allocType);
17181718
}
17191719
}
17201720

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3349,7 +3349,7 @@ class CodeGenFunction : public CodeGenTypeCache {
33493349
SanitizerHandler Handler);
33503350

33513351
/// Emit additional metadata used by the AllocToken instrumentation.
3352-
void EmitAllocTokenHint(llvm::CallBase *CB, QualType AllocType);
3352+
void EmitAllocToken(llvm::CallBase *CB, QualType AllocType);
33533353

33543354
llvm::Value *GetCountedByFieldExprGEP(const Expr *Base, const FieldDecl *FD,
33553355
const FieldDecl *CountDecl);

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2374,11 +2374,10 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
23742374
if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_max_EQ)) {
23752375
StringRef S = Arg->getValue();
23762376
uint64_t Value = 0;
2377-
if (S.getAsInteger(0, Value)) {
2377+
if (S.getAsInteger(0, Value))
23782378
Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
2379-
} else {
2379+
else
23802380
Opts.AllocTokenMax = Value;
2381-
}
23822381
}
23832382

23842383
Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);

clang/test/CodeGenCXX/alloc-token-pointer.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,25 @@ int **test_malloc_ptr() {
3131

3232
// CHECK-LABEL: @_Z12test_new_intv(
3333
int *test_new_int() {
34-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 4, i64 0){{.*}} !alloc_token_hint
34+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 4, i64 0){{.*}} !alloc_token
3535
return new int;
3636
}
3737

3838
// CHECK-LABEL: @_Z20test_new_ulong_arrayv(
3939
unsigned long *test_new_ulong_array() {
40-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 80, i64 0){{.*}} !alloc_token_hint
40+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 80, i64 0){{.*}} !alloc_token
4141
return new unsigned long[10];
4242
}
4343

4444
// CHECK-LABEL: @_Z12test_new_ptrv(
4545
int **test_new_ptr() {
46-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 8, i64 1){{.*}} !alloc_token_hint
46+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 8, i64 1){{.*}} !alloc_token
4747
return new int*;
4848
}
4949

5050
// CHECK-LABEL: @_Z18test_new_ptr_arrayv(
5151
int **test_new_ptr_array() {
52-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 80, i64 1){{.*}} !alloc_token_hint
52+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 80, i64 1){{.*}} !alloc_token
5353
return new int*[10];
5454
}
5555

@@ -108,13 +108,13 @@ ContainsPtr *test_operatornew_struct_array_with_ptr2() {
108108

109109
// CHECK-LABEL: @_Z24test_new_struct_with_ptrv(
110110
ContainsPtr *test_new_struct_with_ptr() {
111-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 16, i64 1){{.*}} !alloc_token_hint
111+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 16, i64 1){{.*}} !alloc_token
112112
return new ContainsPtr;
113113
}
114114

115115
// CHECK-LABEL: @_Z30test_new_struct_array_with_ptrv(
116116
ContainsPtr *test_new_struct_array_with_ptr() {
117-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 160, i64 1){{.*}} !alloc_token_hint
117+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 160, i64 1){{.*}} !alloc_token
118118
return new ContainsPtr[10];
119119
}
120120

@@ -127,13 +127,13 @@ class TestClass {
127127

128128
// CHECK-LABEL: @_Z14test_new_classv(
129129
TestClass *test_new_class() {
130-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 64, i64 0){{.*}} !alloc_token_hint
130+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 64, i64 0){{.*}} !alloc_token
131131
return new TestClass();
132132
}
133133

134134
// CHECK-LABEL: @_Z20test_new_class_arrayv(
135135
TestClass *test_new_class_array() {
136-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 648, i64 0){{.*}} !alloc_token_hint
136+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 648, i64 0){{.*}} !alloc_token
137137
return new TestClass[10];
138138
}
139139

@@ -147,13 +147,13 @@ class VirtualTestClass {
147147

148148
// CHECK-LABEL: @_Z22test_new_virtual_classv(
149149
VirtualTestClass *test_new_virtual_class() {
150-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 72, i64 1){{.*}} !alloc_token_hint
150+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 72, i64 1){{.*}} !alloc_token
151151
return new VirtualTestClass();
152152
}
153153

154154
// CHECK-LABEL: @_Z28test_new_virtual_class_arrayv(
155155
VirtualTestClass *test_new_virtual_class_array() {
156-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 728, i64 1){{.*}} !alloc_token_hint
156+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 728, i64 1){{.*}} !alloc_token
157157
return new VirtualTestClass[10];
158158
}
159159

clang/test/CodeGenCXX/alloc-token.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,25 @@ void test_operator_new_nothrow() {
6969

7070
// CHECK-LABEL: @_Z8test_newv(
7171
int *test_new() {
72-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 4, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token_hint
72+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 4, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token
7373
return new int;
7474
}
7575

7676
// CHECK-LABEL: @_Z14test_new_arrayv(
7777
int *test_new_array() {
78-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 40, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token_hint
78+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 40, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token
7979
return new int[10];
8080
}
8181

8282
// CHECK-LABEL: @_Z16test_new_nothrowv(
8383
int *test_new_nothrow() {
84-
// CHECK: call {{.*}} ptr @__alloc_token_ZnwmRKSt9nothrow_t(i64 noundef 4, ptr {{.*}} @_ZSt7nothrow, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token_hint
84+
// CHECK: call {{.*}} ptr @__alloc_token_ZnwmRKSt9nothrow_t(i64 noundef 4, ptr {{.*}} @_ZSt7nothrow, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token
8585
return new (std::nothrow) int;
8686
}
8787

8888
// CHECK-LABEL: @_Z22test_new_array_nothrowv(
8989
int *test_new_array_nothrow() {
90-
// CHECK: call {{.*}} ptr @__alloc_token_ZnamRKSt9nothrow_t(i64 noundef 40, ptr {{.*}} @_ZSt7nothrow, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token_hint
90+
// CHECK: call {{.*}} ptr @__alloc_token_ZnamRKSt9nothrow_t(i64 noundef 40, ptr {{.*}} @_ZSt7nothrow, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token
9191
return new (std::nothrow) int[10];
9292
}
9393

@@ -123,7 +123,7 @@ void may_throw();
123123
TestClass *test_exception_handling_new() {
124124
try {
125125
// CHECK: invoke {{.*}} ptr @__alloc_token_Znwm(i64 noundef 72, i64 {{[1-9][0-9]*}})
126-
// CHECK-NEXT: !alloc_token_hint
126+
// CHECK-NEXT: !alloc_token
127127
TestClass *obj = new TestClass();
128128
may_throw();
129129
return obj;
@@ -134,15 +134,15 @@ TestClass *test_exception_handling_new() {
134134

135135
// CHECK-LABEL: @_Z14test_new_classv(
136136
TestClass *test_new_class() {
137-
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 72, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token_hint
137+
// CHECK: call {{.*}} ptr @__alloc_token_Znwm(i64 noundef 72, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token
138138
TestClass *obj = new TestClass();
139139
obj->data[0] = 42;
140140
return obj;
141141
}
142142

143143
// CHECK-LABEL: @_Z20test_new_class_arrayv(
144144
TestClass *test_new_class_array() {
145-
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 728, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token_hint
145+
// CHECK: call {{.*}} ptr @__alloc_token_Znam(i64 noundef 728, i64 {{[1-9][0-9]*}}){{.*}} !alloc_token
146146
TestClass* arr = new TestClass[10];
147147
arr[0].data[0] = 123;
148148
return arr;

llvm/docs/LangRef.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2428,7 +2428,7 @@ For example:
24282428
attributed with ``sanitize_realtime``.
24292429
This attribute is incompatible with the ``sanitize_realtime`` attribute.
24302430
``sanitize_alloc_token``
2431-
This attributes indicates that implicit allocation token instrumentation
2431+
This attribute indicates that implicit allocation token instrumentation
24322432
is enabled for this function.
24332433
``speculative_load_hardening``
24342434
This attribute indicates that
@@ -8392,6 +8392,13 @@ Example:
83928392
The ``nofree`` metadata indicates the memory pointed by the pointer will not be
83938393
freed after the attached instruction.
83948394

8395+
'``alloc_token``' Metadata
8396+
^^^^^^^^^^^^^^^^^^^^^^^^^^
8397+
8398+
The ``alloc_token`` metadata may be attached to calls to memory allocation
8399+
functions, and contains richer semantic information about the type of the
8400+
allocation. This information is consumed by the ``alloc-token`` pass to
8401+
instrument such calls with allocation token IDs.
83958402

83968403
Module Flags Metadata
83978404
=====================

0 commit comments

Comments
 (0)