clang: lib/AST/Randstruct.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
20#include "llvm/ADT/SmallVector.h"
21
22#include
23#include
24#include
25#include
26
30
31namespace {
32
33
34enum { CACHE_LINE = 64 };
35
36
37
38class Bucket {
41
42public:
43 virtual ~Bucket() = default;
44
46 void addField(FieldDecl *Field, int FieldSize);
47 virtual bool canFit(int FieldSize) const {
48 return Size + FieldSize <= CACHE_LINE;
49 }
50 virtual bool isBitfieldRun() const { return false; }
51 bool full() const { return Size >= CACHE_LINE; }
52};
53
54void Bucket::addField(FieldDecl *Field, int FieldSize) {
55 Size += FieldSize;
56 Fields.push_back(Field);
57}
58
59struct BitfieldRunBucket : public Bucket {
60 bool canFit(int FieldSize) const override { return true; }
61 bool isBitfieldRun() const override { return true; }
62};
63
64void randomizeStructureLayoutImpl(const ASTContext &Context,
66 std::mt19937 &RNG) {
67
69
70
71 std::unique_ptr CurrentBucket;
72
73
74
75 std::unique_ptr CurrentBitfieldRun;
76
77
78
79 size_t Skipped = 0;
80
81 while (!FieldsOut.empty()) {
82
83
84
85 if (Skipped >= FieldsOut.size()) {
86 Skipped = 0;
87 Buckets.push_back(std::move(CurrentBucket));
88 }
89
90
91 auto FieldIter = FieldsOut.begin();
93
95
96 if (!CurrentBitfieldRun)
97 CurrentBitfieldRun = std::make_unique();
98
99
100
101 CurrentBitfieldRun->addField(FD, 1);
102 FieldsOut.erase(FieldIter);
103 continue;
104 }
105
106
107
108 if (CurrentBitfieldRun)
109 Buckets.push_back(std::move(CurrentBitfieldRun));
110
111
112 if (!CurrentBucket)
113 CurrentBucket = std::make_unique();
114
116 if (Width >= CACHE_LINE) {
117 std::unique_ptr OverSized = std::make_unique();
118 OverSized->addField(FD, Width);
119 FieldsOut.erase(FieldIter);
120 Buckets.push_back(std::move(OverSized));
121 continue;
122 }
123
124
125 if (CurrentBucket->canFit(Width)) {
126 CurrentBucket->addField(FD, Width);
127 FieldsOut.erase(FieldIter);
128
129
130 if (CurrentBucket->full()) {
131 Skipped = 0;
132 Buckets.push_back(std::move(CurrentBucket));
133 }
134 } else {
135
136
137 ++Skipped;
138 FieldsOut.push_back(FD);
139 FieldsOut.erase(FieldIter);
140 }
141 }
142
143
144
145
146 if (CurrentBucket)
147 Buckets.push_back(std::move(CurrentBucket));
148
149
150 if (CurrentBitfieldRun)
151 Buckets.push_back(std::move(CurrentBitfieldRun));
152
153 std::shuffle(std::begin(Buckets), std::end(Buckets), RNG);
154
155
157 for (const std::unique_ptr &B : Buckets) {
159 if (!B->isBitfieldRun())
160 std::shuffle(std::begin(RandFields), std::end(RandFields), RNG);
161
162 FinalOrder.insert(FinalOrder.end(), RandFields.begin(), RandFields.end());
163 }
164
165 FieldsOut = FinalOrder;
166}
167
168}
169
171namespace randstruct {
172
177
178 unsigned TotalNumFields = 0;
180 ++TotalNumFields;
181 if (auto *FD = dyn_cast(D))
182 RandomizedFields.push_back(FD);
183 else if (isa(D) || isa(D))
184 PostRandomizedFields.push_back(D);
185 else
186 FinalOrdering.push_back(D);
187 }
188
189 if (RandomizedFields.empty())
190 return false;
191
192
193
196 if (!FlexibleArray) {
197 if (const auto *CA =
198 dyn_cast(RandomizedFields.back()->getType()))
199 if (CA->getSize().sle(2))
200 FlexibleArray = RandomizedFields.pop_back_val();
201 }
202
203 std::string Seed =
205 std::seed_seq SeedSeq(Seed.begin(), Seed.end());
206 std::mt19937 RNG(SeedSeq);
207
208 randomizeStructureLayoutImpl(Context, RandomizedFields, RNG);
209
210
211 FinalOrdering.insert(FinalOrdering.end(), RandomizedFields.begin(),
212 RandomizedFields.end());
213
214
215 FinalOrdering.insert(FinalOrdering.end(), PostRandomizedFields.begin(),
216 PostRandomizedFields.end());
217
218
219 if (FlexibleArray)
220 FinalOrdering.push_back(FlexibleArray);
221
222 assert(TotalNumFields == FinalOrdering.size() &&
223 "Decl count has been altered after Randstruct randomization!");
224 (void)TotalNumFields;
225 return true;
226}
227
228}
229}
Defines the clang::ASTContext interface.
Defines the Diagnostic-related interfaces.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const LangOptions & getLangOpts() const
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
bool isZeroLengthBitField() const
Is this a zero-length bit-field? Such bit-fields aren't really bit-fields at all and instead act as a...
std::string RandstructSeed
The seed used by the randomize structure layout feature.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Represents a struct/union/class.
bool hasFlexibleArrayMember() const
bool randomizeStructureLayout(const ASTContext &Context, RecordDecl *RD, llvm::SmallVectorImpl< Decl * > &FinalOrdering)
The JSON file list parser is used to communicate input to InstallAPI.