Skip to content

Commit a8106ca

Browse files
committed
Merge branch 'randstruct-auto' into Autoselect
2 parents 97166c8 + 3e53f43 commit a8106ca

File tree

11 files changed

+77
-9
lines changed

11 files changed

+77
-9
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef RANDSTRUCTSEED_H
2+
#define RANDSTRUCTSEED_H
3+
#include <string>
4+
namespace clang {
5+
extern std::string RandstructSeed;
6+
extern bool RandstructAutoSelect;
7+
}
8+
#endif

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3206,5 +3206,5 @@ def RandomizeLayout : InheritableAttr {
32063206
let Spellings = [GCC<"randomize_layout">, Declspec<"randomize_layout">,
32073207
Keyword<"randomize_layout">];
32083208
let Subjects = SubjectList<[Record]>;
3209-
let Documentation = [Undocumented];
3209+
let Documentation = [ClangRandstructDocs];
32103210
}

clang/include/clang/Basic/AttrDocs.td

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4094,4 +4094,22 @@ Likewise, when applied to a strong local variable, that variable becomes
40944094
``const`` and is considered externally-retained.
40954095

40964096
When compiled without ``-fobjc-arc``, this attribute is ignored.
4097-
}]; }
4097+
}];
4098+
}
4099+
4100+
def ClangRandstructDocs : Documentation {
4101+
let Category = DocCatVariable;
4102+
let Content = [{
4103+
The attribute ``randomize_layout`` can be applied to the declaration of
4104+
a record. ``randomize_layout`` instructs the compiler to randomize the memory layout
4105+
of the member variables of the record.
4106+
.. code-block:: c
4107+
4108+
// Indicates that this struct should be randomized by Randstruct implementation.
4109+
struct s {
4110+
char *a;
4111+
char *b;
4112+
char *c;
4113+
}__attribute__((randomize_layout));
4114+
}];
4115+
}

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,4 +343,6 @@ def warn_padded_struct_size : Warning<
343343
InGroup<Padded>, DefaultIgnore;
344344
def warn_unnecessary_packed : Warning<
345345
"packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
346+
def warn_randomize_attr_union : Warning<
347+
"union declared with 'randomize_layout' attribute">, InGroup<DiagGroup<"randomize-layout">>;
346348
}

clang/include/clang/Driver/CC1Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ def fcaret_diagnostics_max_lines :
422422
HelpText<"Set the maximum number of source lines to show in a caret diagnostic">;
423423
def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
424424
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
425+
def randstruct_seed : Separate<["-"], "randstruct-seed">, MetaVarName<"<N>">,
426+
HelpText<"Randomization seed for random struct layouts">;
425427
def verify_EQ : CommaJoined<["-"], "verify=">,
426428
MetaVarName<"<prefixes>">,
427429
HelpText<"Verify diagnostic output using comment directives that start with"

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,7 @@ def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
12581258
def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>,
12591259
Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">;
12601260
def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>;
1261+
def randstruct_seed_EQ : Joined<["-"], "randstruct-seed=">, Group<f_Group>;
12611262
def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
12621263
HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
12631264
def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
@@ -1750,6 +1751,9 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group<f_Group>,
17501751
HelpText<"Turn on loop reroller">, Flags<[CC1Option]>;
17511752
def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<f_Group>,
17521753
HelpText<"Turn off loop reroller">;
1754+
def randstruct_auto : Flag<["-"], "randstruct-auto">,
1755+
HelpText<"Enable automatic structure selection for field randomization; "
1756+
"disabled with no_randomize_layout">, Flags<[CC1Option]>;
17531757
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
17541758
HelpText<"Process trigraph sequences">, Flags<[CC1Option]>;
17551759
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,

clang/lib/AST/RecordFieldReorganizer.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "clang/AST/RecordFieldReorganizer.h"
1515
#include "clang/AST/ASTContext.h"
16+
#include "clang/AST/RandstructSeed.h"
1617

1718
#include <algorithm>
1819
#include <cstdint>
@@ -23,6 +24,8 @@
2324
// FIXME: Find a better alternative to SmallVector with hardcoded size!
2425

2526
namespace clang {
27+
std::string RandstructSeed = "";
28+
bool RandstructAutoSelect = false;
2629

2730
void RecordFieldReorganizer::reorganizeFields(const ASTContext &C,
2831
const RecordDecl *D) const {
@@ -93,7 +96,8 @@ const size_t CACHE_LINE = 64;
9396

9497
SmallVector<FieldDecl *, 64> Bucket::randomize() {
9598
// FIXME use seed
96-
auto rng = std::default_random_engine{};
99+
std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end());
100+
auto rng = std::default_random_engine{Seq};
97101
std::shuffle(std::begin(fields), std::end(fields), rng);
98102
return fields;
99103
}
@@ -140,7 +144,8 @@ bool BitfieldRun::canFit(size_t size) const {
140144
bool BitfieldRun::isBitfieldRun() const { return true; }
141145

142146
SmallVector<Decl *, 64> randomize(SmallVector<Decl *, 64> fields) {
143-
auto rng = std::default_random_engine{};
147+
std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end());
148+
auto rng = std::default_random_engine{Seq};
144149
std::shuffle(std::begin(fields), std::end(fields), rng);
145150
return fields;
146151
}
@@ -229,7 +234,8 @@ SmallVector<Decl *, 64> perfrandomize(const ASTContext &ctx,
229234
buckets.push_back(std::move(currentBitfieldRun));
230235
}
231236

232-
auto rng = std::default_random_engine{};
237+
std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end());
238+
auto rng = std::default_random_engine{Seq};
233239
std::shuffle(std::begin(buckets), std::end(buckets), rng);
234240

235241
// Produce the new ordering of the elements from our buckets.

clang/lib/AST/RecordLayoutBuilder.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "clang/AST/RandstructSeed.h"
910
#include "clang/AST/RecordLayout.h"
1011
#include "clang/AST/ASTContext.h"
1112
#include "clang/AST/ASTDiagnostic.h"
@@ -2986,10 +2987,18 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
29862987
if (Entry) return *Entry;
29872988

29882989
const ASTRecordLayout *NewEntry = nullptr;
2989-
bool ShouldBeRandomized = Randstruct::isTriviallyRandomizable(D) || D->getAttr<RandomizeLayoutAttr>() != nullptr;
2990-
if(ShouldBeRandomized){
2991-
Randstruct randstruct;
2992-
randstruct.reorganizeFields(*this, D);
2990+
2991+
bool ShouldBeRandomized = (RandstructAutoSelect && Randstruct::isTriviallyRandomizable(D)) || D->getAttr<RandomizeLayoutAttr>() != nullptr;
2992+
if (ShouldBeRandomized) {
2993+
// There is no technical benefit to randomizing the fields of a union
2994+
// since they all share the same offset of zero.
2995+
if (D->isUnion()) {
2996+
getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_union);
2997+
}
2998+
else {
2999+
Randstruct randstruct;
3000+
randstruct.reorganizeFields(*this,D);
3001+
}
29933002
}
29943003

29953004
if (isMsLayout(*this)) {

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4405,6 +4405,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
44054405
CmdArgs.push_back(Args.MakeArgString(Twine(N)));
44064406
}
44074407

4408+
// -randstruct-seed parent process
4409+
if (Arg *A = Args.getLastArg(options::OPT_randstruct_seed_EQ)) {
4410+
CmdArgs.push_back( "-randstruct-seed" );
4411+
CmdArgs.push_back(A->getValue(0));
4412+
}
4413+
4414+
if (Arg *A = Args.getLastArg(options::OPT_randstruct_auto)) {
4415+
CmdArgs.push_back( "-randstruct-auto" );
4416+
}
4417+
44084418
// -fvisibility= and -fvisibility-ms-compat are of a piece.
44094419
if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
44104420
options::OPT_fvisibility_ms_compat)) {

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "clang/AST/RandstructSeed.h"
910
#include "clang/Frontend/CompilerInvocation.h"
1011
#include "TestModuleFileExtension.h"
1112
#include "clang/Basic/Builtins.h"
@@ -1669,6 +1670,13 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
16691670
Opts.ProgramAction = frontend::PluginAction;
16701671
Opts.ActionName = A->getValue();
16711672
}
1673+
// child process handle arguments
1674+
if (const Arg* A = Args.getLastArg(OPT_randstruct_seed)) {
1675+
RandstructSeed = A->getValue(0);
1676+
}
1677+
if (const Arg* A = Args.getLastArg(OPT_randstruct_auto)) {
1678+
RandstructAutoSelect = true;
1679+
}
16721680
Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
16731681
for (const auto *AA : Args.filtered(OPT_plugin_arg))
16741682
Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
// CHECK-NEXT: Overloadable (SubjectMatchRule_function)
118118
// CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter)
119119
// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
120+
// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record)
120121
// CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function)
121122
// CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function)
122123
// CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global)

0 commit comments

Comments
 (0)