20#include "llvm/ADT/SmallVector.h"
34enum { CACHE_LINE = 64 };
43 virtual ~Bucket() =
default;
46 void addField(
FieldDecl *Field,
int FieldSize);
47 virtual bool canFit(
int FieldSize)
const {
48 return Size + FieldSize <= CACHE_LINE;
50 virtual bool isBitfieldRun()
const {
return false; }
51 bool full()
const {
return Size >= CACHE_LINE; }
54void Bucket::addField(
FieldDecl *Field,
int FieldSize) {
56 Fields.push_back(Field);
59struct BitfieldRunBucket :
public Bucket {
60 bool canFit(
int FieldSize)
const override {
return true; }
61 bool isBitfieldRun()
const override {
return true; }
64void randomizeStructureLayoutImpl(
const ASTContext &Context,
71 std::unique_ptr<Bucket> CurrentBucket;
75 std::unique_ptr<BitfieldRunBucket> CurrentBitfieldRun;
81 while (!FieldsOut.empty()) {
85 if (Skipped >= FieldsOut.size()) {
87 Buckets.push_back(std::move(CurrentBucket));
91 auto FieldIter = FieldsOut.begin();
96 if (!CurrentBitfieldRun)
97 CurrentBitfieldRun = std::make_unique<BitfieldRunBucket>();
101 CurrentBitfieldRun->addField(FD, 1);
102 FieldsOut.erase(FieldIter);
108 if (CurrentBitfieldRun)
109 Buckets.push_back(std::move(CurrentBitfieldRun));
113 CurrentBucket = std::make_unique<Bucket>();
116 if (Width >= CACHE_LINE) {
117 std::unique_ptr<Bucket> OverSized = std::make_unique<Bucket>();
118 OverSized->addField(FD, Width);
119 FieldsOut.erase(FieldIter);
120 Buckets.push_back(std::move(OverSized));
125 if (CurrentBucket->canFit(Width)) {
126 CurrentBucket->addField(FD, Width);
127 FieldsOut.erase(FieldIter);
130 if (CurrentBucket->full()) {
132 Buckets.push_back(std::move(CurrentBucket));
138 FieldsOut.push_back(FD);
139 FieldsOut.erase(FieldIter);
147 Buckets.push_back(std::move(CurrentBucket));
150 if (CurrentBitfieldRun)
151 Buckets.push_back(std::move(CurrentBitfieldRun));
153 std::shuffle(std::begin(Buckets), std::end(Buckets), RNG);
157 for (
const std::unique_ptr<Bucket> &B : Buckets) {
159 if (!B->isBitfieldRun())
160 std::shuffle(std::begin(RandFields), std::end(RandFields), RNG);
162 FinalOrder.insert(FinalOrder.end(), RandFields.begin(), RandFields.end());
165 FieldsOut = FinalOrder;
171namespace randstruct {
178 unsigned TotalNumFields = 0;
181 if (
auto *FD = dyn_cast<FieldDecl>(
D))
182 RandomizedFields.push_back(FD);
183 else if (isa<StaticAssertDecl>(
D) || isa<IndirectFieldDecl>(
D))
184 PostRandomizedFields.push_back(
D);
186 FinalOrdering.push_back(
D);
189 if (RandomizedFields.empty())
196 if (!FlexibleArray) {
198 dyn_cast<ConstantArrayType>(RandomizedFields.back()->getType()))
199 if (CA->getSize().sle(2))
200 FlexibleArray = RandomizedFields.pop_back_val();
205 std::seed_seq SeedSeq(Seed.begin(), Seed.end());
206 std::mt19937 RNG(SeedSeq);
208 randomizeStructureLayoutImpl(Context, RandomizedFields, RNG);
211 FinalOrdering.insert(FinalOrdering.end(), RandomizedFields.begin(),
212 RandomizedFields.end());
215 FinalOrdering.insert(FinalOrdering.end(), PostRandomizedFields.begin(),
216 PostRandomizedFields.end());
220 FinalOrdering.push_back(FlexibleArray);
222 assert(TotalNumFields == FinalOrdering.size() &&
223 "Decl count has been altered after Randstruct randomization!");
224 (void)TotalNumFields;
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 ASTContext &Ctx) 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.