21#include "llvm/ADT/SmallVector.h"
36enum { CACHE_LINE = 64 };
45 virtual ~Bucket() =
default;
48 void addField(
FieldDecl *Field,
int FieldSize);
49 virtual bool canFit(
int FieldSize)
const {
50 return Size + FieldSize <= CACHE_LINE;
52 virtual bool isBitfieldRun()
const {
return false; }
53 bool full()
const {
return Size >= CACHE_LINE; }
56void Bucket::addField(
FieldDecl *Field,
int FieldSize) {
58 Fields.push_back(Field);
61struct BitfieldRunBucket :
public Bucket {
62 bool canFit(
int FieldSize)
const override {
return true; }
63 bool isBitfieldRun()
const override {
return true; }
66void randomizeStructureLayoutImpl(
const ASTContext &Context,
73 std::unique_ptr<Bucket> CurrentBucket;
77 std::unique_ptr<BitfieldRunBucket> CurrentBitfieldRun;
83 while (!FieldsOut.empty()) {
87 if (Skipped >= FieldsOut.size()) {
89 Buckets.push_back(std::move(CurrentBucket));
93 auto FieldIter = FieldsOut.begin();
98 if (!CurrentBitfieldRun)
99 CurrentBitfieldRun = std::make_unique<BitfieldRunBucket>();
103 CurrentBitfieldRun->addField(FD, 1);
104 FieldsOut.erase(FieldIter);
110 if (CurrentBitfieldRun)
111 Buckets.push_back(std::move(CurrentBitfieldRun));
115 CurrentBucket = std::make_unique<Bucket>();
118 if (Width >= CACHE_LINE) {
119 std::unique_ptr<Bucket> OverSized = std::make_unique<Bucket>();
120 OverSized->addField(FD, Width);
121 FieldsOut.erase(FieldIter);
122 Buckets.push_back(std::move(OverSized));
127 if (CurrentBucket->canFit(Width)) {
128 CurrentBucket->addField(FD, Width);
129 FieldsOut.erase(FieldIter);
132 if (CurrentBucket->full()) {
134 Buckets.push_back(std::move(CurrentBucket));
140 FieldsOut.push_back(FD);
141 FieldsOut.erase(FieldIter);
149 Buckets.push_back(std::move(CurrentBucket));
152 if (CurrentBitfieldRun)
153 Buckets.push_back(std::move(CurrentBitfieldRun));
155 std::shuffle(std::begin(Buckets), std::end(Buckets), RNG);
159 for (
const std::unique_ptr<Bucket> &B : Buckets) {
161 if (!B->isBitfieldRun())
162 std::shuffle(std::begin(RandFields), std::end(RandFields), RNG);
164 FinalOrder.insert(FinalOrder.end(), RandFields.begin(), RandFields.end());
167 FieldsOut = FinalOrder;
173namespace randstruct {
180 unsigned TotalNumFields = 0;
183 if (
auto *FD = dyn_cast<FieldDecl>(
D))
184 RandomizedFields.push_back(FD);
185 else if (isa<StaticAssertDecl>(
D) || isa<IndirectFieldDecl>(
D))
186 PostRandomizedFields.push_back(
D);
188 FinalOrdering.push_back(
D);
191 if (RandomizedFields.empty())
198 if (!FlexibleArray) {
200 dyn_cast<ConstantArrayType>(RandomizedFields.back()->getType()))
201 if (CA->getSize().sle(2))
202 FlexibleArray = RandomizedFields.pop_back_val();
207 std::seed_seq SeedSeq(Seed.begin(), Seed.end());
208 std::mt19937 RNG(SeedSeq);
210 randomizeStructureLayoutImpl(Context, RandomizedFields, RNG);
213 FinalOrdering.insert(FinalOrdering.end(), RandomizedFields.begin(),
214 RandomizedFields.end());
217 FinalOrdering.insert(FinalOrdering.end(), PostRandomizedFields.begin(),
218 PostRandomizedFields.end());
222 FinalOrdering.push_back(FlexibleArray);
224 assert(TotalNumFields == FinalOrdering.size() &&
225 "Decl count has been altered after Randstruct randomization!");
226 (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.