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.