From 3b9829ee86f311ab232f8cbb49cf5b5e7fcd70ef Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Fri, 1 Feb 2019 13:53:17 -0800 Subject: [PATCH 01/87] Add "randomize_layout" attribute --- clang/include/clang/Basic/Attr.td | 7 +++++++ clang/lib/Sema/SemaDeclAttr.cpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b0bc73134b044f..0d06337127d488 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3186,3 +3186,10 @@ def ObjCExternallyRetained : InheritableAttr { let Subjects = SubjectList<[NonParmVar, Function, Block, ObjCMethod]>; let Documentation = [ObjCExternallyRetainedDocs]; } + +def Randomized : InheritableAttr { + let Spellings = [GCC<"randomize_layout">, Declspec<"randomize_layout">, + Keyword<"randomize_layout">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 24e07599186e0a..7b471105abfe69 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6788,6 +6788,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttributeWithExclusions(S, D, AL); break; + case ParsedAttr::AT_Randomized: + handleSimpleAttribute(S, D, AL); + break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; From 9b0f3deecafd42731e156653044764e06c970cf7 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Fri, 1 Feb 2019 13:53:42 -0800 Subject: [PATCH 02/87] testing: Emit message when randomize_layout --- clang/lib/AST/RecordLayoutBuilder.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index be759e52a1c8e4..79fa08af4df3cb 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -5,7 +5,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// - #include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -1362,7 +1361,13 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // the future, this will need to be tweakable by targets. bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); bool HasFlexibleArrayMember = D->hasFlexibleArrayMember(); - for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) { + + bool ShouldBeRandomized = D->getAttr() != nullptr; + if (ShouldBeRandomized) { + llvm::outs() << D->getNameAsString() << "\n"; + } + + for (auto I = fields.begin(), End = fields.end(); I != End; ++I) { auto Next(I); ++Next; LayoutField(*I, From f8da259829202a755af6c788d24fd049c3e65950 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Fri, 1 Feb 2019 14:28:03 -0800 Subject: [PATCH 03/87] Rename Randomized to RandomizeLayout --- clang/include/clang/Basic/Attr.td | 2 +- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- clang/lib/Sema/SemaDeclAttr.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 0d06337127d488..f1e2c520be018d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3187,7 +3187,7 @@ def ObjCExternallyRetained : InheritableAttr { let Documentation = [ObjCExternallyRetainedDocs]; } -def Randomized : InheritableAttr { +def RandomizeLayout : InheritableAttr { let Spellings = [GCC<"randomize_layout">, Declspec<"randomize_layout">, Keyword<"randomize_layout">]; let Subjects = SubjectList<[Record]>; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 79fa08af4df3cb..4122e60730b050 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1362,7 +1362,7 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); bool HasFlexibleArrayMember = D->hasFlexibleArrayMember(); - bool ShouldBeRandomized = D->getAttr() != nullptr; + bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { llvm::outs() << D->getNameAsString() << "\n"; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 7b471105abfe69..d19856f4df8668 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6788,8 +6788,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttributeWithExclusions(S, D, AL); break; - case ParsedAttr::AT_Randomized: - handleSimpleAttribute(S, D, AL); + case ParsedAttr::AT_RandomizeLayout: + handleSimpleAttribute(S, D, AL); break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); From 7d221cd5945ec72253d1c0866606ecc8c2bacc3b Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Fri, 1 Feb 2019 15:34:16 -0800 Subject: [PATCH 04/87] fix: Go back to using D's field iterators --- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 4122e60730b050..f98ebd01c78879 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1367,7 +1367,7 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { llvm::outs() << D->getNameAsString() << "\n"; } - for (auto I = fields.begin(), End = fields.end(); I != End; ++I) { + for (auto I = D->field.begin(), End = D->field.end(); I != End; ++I) { auto Next(I); ++Next; LayoutField(*I, From 5749304c1a30a329e9932bdd5997ee20f8a39284 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Fri, 1 Feb 2019 16:33:41 -0800 Subject: [PATCH 05/87] fix: Oops, actually use correct iterators --- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f98ebd01c78879..3f676be653a18d 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1367,7 +1367,7 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { llvm::outs() << D->getNameAsString() << "\n"; } - for (auto I = D->field.begin(), End = D->field.end(); I != End; ++I) { + for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) { auto Next(I); ++Next; LayoutField(*I, From 18bcbc028620a9382493a0cd4a1d911cc2c44dcc Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Wed, 6 Feb 2019 16:57:52 -0800 Subject: [PATCH 06/87] Add reorder method for RecordDecl --- clang/include/clang/AST/Decl.h | 2 ++ clang/lib/AST/Decl.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 933166691a0145..0f201aaa979a7e 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3814,6 +3814,8 @@ class RecordDecl : public TagDecl { /// nullptr is returned if no named data member exists. const FieldDecl *findFirstNamedDataMember() const; + void reorderFields(ArrayRef Decls) const; + private: /// Deserialize just the fields. void LoadFieldsFromExternalStorage() const; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 98962461a7e1f8..520a0891973adc 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4148,6 +4148,14 @@ RecordDecl::field_iterator RecordDecl::field_begin() const { return field_iterator(decl_iterator(FirstDecl)); } +void RecordDecl::reorderFields(ArrayRef Decls) const { + Decl *NewFirst, *NewLast; + std::tie(NewFirst, NewLast) = + BuildDeclChain(Decls, false); + FirstDecl = NewFirst; + LastDecl = NewLast; +} + /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { From 8a2770761d9d352dab19f26154c8f294dc4388c1 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Wed, 6 Feb 2019 16:59:54 -0800 Subject: [PATCH 07/87] Fix infinite loop by updating tail ptr --- clang/lib/AST/DeclBase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index a44c83981586ec..5331fc657dc1bd 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1257,6 +1257,9 @@ DeclContext::BuildDeclChain(ArrayRef Decls, PrevDecl = D; } + // The last one in the chain should have a null next! + PrevDecl->NextInContextAndBits.setPointer(nullptr); + return std::make_pair(FirstNewDecl, PrevDecl); } From a3fa3ddd227c8d2bb62f375815bbc3a167deda16 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Wed, 6 Feb 2019 17:00:14 -0800 Subject: [PATCH 08/87] Hack: quick and dirty randomization for testing! --- clang/lib/AST/RecordLayoutBuilder.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 3f676be653a18d..8f66b63e443056 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -19,6 +19,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" +#include +#include + using namespace clang; namespace { @@ -1362,14 +1365,27 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); bool HasFlexibleArrayMember = D->hasFlexibleArrayMember(); + // A staging area to easily reorder the fields + SmallVector fields; + for (auto f : D->fields()) { + fields.push_back(f); + } + bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { - llvm::outs() << D->getNameAsString() << "\n"; + // FIXME Should call our Randstruct code once we port it. + auto rng = std::default_random_engine {}; + std::shuffle(std::begin(fields), std::end(fields), rng); + + // This will rebuild the Decl chain of fields + D->reorderFields(fields); } + for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) { auto Next(I); ++Next; + LayoutField(*I, InsertExtraPadding && (Next != End || !HasFlexibleArrayMember)); } From 4ff065bf33a8ac81d32898fe6d636ec92f0eae0c Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Wed, 6 Feb 2019 17:04:57 -0800 Subject: [PATCH 09/87] Move Randomization to getASTRecordLayout --- clang/lib/AST/RecordLayoutBuilder.cpp | 35 ++++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 8f66b63e443056..3bfdbb4bb3d636 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1365,23 +1365,6 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); bool HasFlexibleArrayMember = D->hasFlexibleArrayMember(); - // A staging area to easily reorder the fields - SmallVector fields; - for (auto f : D->fields()) { - fields.push_back(f); - } - - bool ShouldBeRandomized = D->getAttr() != nullptr; - if (ShouldBeRandomized) { - // FIXME Should call our Randstruct code once we port it. - auto rng = std::default_random_engine {}; - std::shuffle(std::begin(fields), std::end(fields), rng); - - // This will rebuild the Decl chain of fields - D->reorderFields(fields); - } - - for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) { auto Next(I); ++Next; @@ -3005,6 +2988,24 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; + // FIXME Randstruct code should be called here! + // A staging area to easily reorder the fields + SmallVector fields; + for (auto f : D->fields()) { + fields.push_back(f); + } + + bool ShouldBeRandomized = D->getAttr() != nullptr; + if (ShouldBeRandomized) { + // FIXME Should call our Randstruct code once we port it. + auto rng = std::default_random_engine {}; + std::shuffle(std::begin(fields), std::end(fields), rng); + + // This will rebuild the Decl chain of fields + D->reorderFields(fields); + } + // FIXME end Randstruct code + if (isMsLayout(*this)) { MicrosoftRecordLayoutBuilder Builder(*this); if (const auto *RD = dyn_cast(D)) { From 5d6b7c1ed2f07593262badd0e6da3d99a975b711 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 11 Feb 2019 19:39:18 -0800 Subject: [PATCH 10/87] Added the 'no_randomize_layout' attr to clang --- clang/include/clang/Basic/Attr.td | 7 +++++++ clang/lib/Sema/SemaDeclAttr.cpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index f1e2c520be018d..f1cea8510df5c2 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3193,3 +3193,10 @@ def RandomizeLayout : InheritableAttr { let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; } + +def NoRandomizeLayout : InheritableAttr { + let Spellings = [GCC<"no_randomize_layout">, Declspec<"no_randomize_layout">, + Keyword<"no_randomize_layout">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d19856f4df8668..95a09dbcaed108 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6791,6 +6791,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_RandomizeLayout: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_NoRandomizeLayout: + handleSimpleAttribute(S, D, AL); + break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; From 1ed67efa255720d091cad8b01dde0bce55161e52 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Wed, 13 Feb 2019 22:47:12 +0000 Subject: [PATCH 11/87] Add performance sensitive randomization Co-authored-by: James Foster --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/LayoutFieldRandomizer.cpp | 217 ++++++++++++++++++++++++ clang/lib/AST/LayoutFieldRandomizer.h | 27 +++ clang/lib/AST/RecordLayoutBuilder.cpp | 23 +-- 4 files changed, 254 insertions(+), 14 deletions(-) create mode 100644 clang/lib/AST/LayoutFieldRandomizer.cpp create mode 100644 clang/lib/AST/LayoutFieldRandomizer.h diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 570ca718acf5dc..ad9f283be48657 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -44,6 +44,7 @@ add_clang_library(clangAST InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp + LayoutFieldRandomizer.cpp Mangle.cpp MicrosoftCXXABI.cpp MicrosoftMangle.cpp diff --git a/clang/lib/AST/LayoutFieldRandomizer.cpp b/clang/lib/AST/LayoutFieldRandomizer.cpp new file mode 100644 index 00000000000000..1ec73e71923b38 --- /dev/null +++ b/clang/lib/AST/LayoutFieldRandomizer.cpp @@ -0,0 +1,217 @@ +//===----- LayoutFieldRandomizer.cpp - Randstruct Implementation -*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Cache line best-effort field randomization +// +//===----------------------------------------------------------------------===// + +#include "LayoutFieldRandomizer.h" +#include "llvm/ADT/SmallVector.h" + +#include +#include +#include +#include + +namespace clang { + +/// Bucket to store fields up to size of a cache line during randomization. +class Bucket { +public: + virtual ~Bucket() = default; + /// Returns a randomized version of the bucket. + virtual SmallVector randomize(); + /// Checks if an added element would fit in a cache line. + virtual bool canFit(size_t size) const; + /// Adds a field to the bucket. + void add(FieldDecl *field, size_t size); + /// Is this bucket for bitfields? + virtual bool isBitfieldRun() const; + /// Is this bucket full? + bool full() const; + bool empty() const; + +protected: + size_t size; + SmallVector fields; +}; + +/// BitfieldRun is a bucket for storing adjacent bitfields that may +/// exceed the size of a cache line. +class BitfieldRun : public Bucket { +public: + virtual SmallVector randomize() override; + virtual bool canFit(size_t size) const override; + virtual bool isBitfieldRun() const override; +}; + +// TODO: Is there a way to detect this? (i.e. on 32bit system vs 64?) +const size_t CACHE_LINE = 64; + +SmallVector Bucket::randomize() { + // TODO use seed + auto rng = std::default_random_engine{}; + std::shuffle(std::begin(fields), std::end(fields), rng); + return fields; +} + +bool Bucket::canFit(size_t size) const { + // We will say we can fit any size if the bucket is empty + // because there are many instances where a field is much + // larger than 64 bits (i.e., an array, a structure, etc) + // but it still must be placed into a bucket. + // + // Otherwise, if the bucket has elements and we're still + // trying to create a cache-line sized grouping, we cannot + // fit a larger field in here. + return empty() || this->size + size <= CACHE_LINE; +} + +void Bucket::add(FieldDecl *field, size_t size) { + fields.push_back(field); + this->size += size; +} + +bool Bucket::isBitfieldRun() const { + // The normal bucket is not a bitfieldrun. This is to avoid RTTI. + return false; +} + +bool Bucket::full() const { + // We're full if our size is a cache line. + return size >= CACHE_LINE; +} + +bool Bucket::empty() const { return size == 0; } + +SmallVector BitfieldRun::randomize() { + // Keep bit fields adjacent, we will not scramble them. + return fields; +} + +bool BitfieldRun::canFit(size_t size) const { + // We can always fit another adjacent bitfield. + return true; +} + +bool BitfieldRun::isBitfieldRun() const { + // Yes. + return true; +} + +SmallVector randomize(SmallVector fields) { + auto rng = std::default_random_engine{}; + std::shuffle(std::begin(fields), std::end(fields), rng); + return fields; +} + +SmallVector perfrandomize(const ASTContext &ctx, + SmallVector fields) { + // All of the buckets produced by best-effort cache-line algorithm. + std::vector> buckets; + + // The current bucket of fields that we are trying to fill to a cache-line. + std::unique_ptr currentBucket = nullptr; + // The current bucket containing the run of adjacent bitfields to ensure + // they remain adjacent. + std::unique_ptr currentBitfieldRun = nullptr; + + // Tracks the number of fields that we failed to fit to the current bucket, + // and thus still need to be added later. + size_t skipped = 0; + + while (!fields.empty()) { + // If we've skipped more fields than we have remaining to place, + // that means that they can't fit in our current bucket, and we + // need to start a new one. + if (skipped >= fields.size()) { + skipped = 0; + buckets.push_back(std::move(currentBucket)); + } + + // Take the first field that needs to be put in a bucket. + auto field = fields.begin(); + auto *f = llvm::cast(*field); + + if (f->isBitField()) { + // Start a bitfield run if this is the first bitfield + // we have found. + if (!currentBitfieldRun) { + currentBitfieldRun = llvm::make_unique(); + } + + // We've placed the field, and can remove it from the + // "awaiting buckets" vector called "fields" + currentBitfieldRun->add(f, 1); + fields.erase(field); + } else { + // Else, current field is not a bitfield + // If we were previously in a bitfield run, end it. + if (currentBitfieldRun) { + buckets.push_back(std::move(currentBitfieldRun)); + } + // If we don't have a bucket, make one. + if (!currentBucket) { + currentBucket = llvm::make_unique(); + } + + // FIXME get access to AST Context + auto width = ctx.getTypeInfo(f->getType()).Width; + + // If we can fit, add it. + if (currentBucket->canFit(width)) { + currentBucket->add(f, width); + fields.erase(field); + + // If it's now full, tie off the bucket. + if (currentBucket->full()) { + skipped = 0; + buckets.push_back(std::move(currentBucket)); + } + } else { + // We can't fit it in our current bucket. + // Move to the end for processing later. + ++skipped; // Mark it skipped. + fields.push_back(f); + fields.erase(field); + } + } + } + + // Done processing the fields awaiting a bucket. + + // If we were filling a bucket, tie it off. + if (currentBucket) { + buckets.push_back(std::move(currentBucket)); + } + + // If we were processing a bitfield run bucket, tie it off. + if (currentBitfieldRun) { + buckets.push_back(std::move(currentBitfieldRun)); + } + + auto rng = std::default_random_engine{}; + std::shuffle(std::begin(buckets), std::end(buckets), rng); + + // Produce the new ordering of the elements from our buckets. + SmallVector finalOrder; + for (auto &bucket : buckets) { + auto randomized = bucket->randomize(); + finalOrder.insert(finalOrder.end(), randomized.begin(), randomized.end()); + } + + return finalOrder; +} + +SmallVector rearrange(const ASTContext &ctx, + SmallVector fields) { + return perfrandomize(ctx, fields); +} + +} // namespace clang diff --git a/clang/lib/AST/LayoutFieldRandomizer.h b/clang/lib/AST/LayoutFieldRandomizer.h new file mode 100644 index 00000000000000..81af1612b39e98 --- /dev/null +++ b/clang/lib/AST/LayoutFieldRandomizer.h @@ -0,0 +1,27 @@ +//===----- LayoutFieldRandomizer.h - Entry Point for Randstruct --*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header file provides the entry point for the Randstruct structure +// layout randomization code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_AST_LAYOUTFIELDRANDOMIZER_H +#define LLVM_CLANG_LIB_AST_LAYOUTFIELDRANDOMIZER_H + +#include "clang/AST/AST.h" + +namespace clang { +/// Rearranges the order of the supplied fields. Will make best effort to fit +// members into a cache line. +SmallVector rearrange(const ASTContext &ctx, + SmallVector fields); +} // namespace clang + +#endif diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 3bfdbb4bb3d636..57cea368d1f308 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -5,6 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + +#include "LayoutFieldRandomizer.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -19,9 +21,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" -#include -#include - using namespace clang; namespace { @@ -2988,23 +2987,19 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; - // FIXME Randstruct code should be called here! - // A staging area to easily reorder the fields - SmallVector fields; - for (auto f : D->fields()) { - fields.push_back(f); - } - bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { - // FIXME Should call our Randstruct code once we port it. - auto rng = std::default_random_engine {}; - std::shuffle(std::begin(fields), std::end(fields), rng); + // A staging area to easily reorder the fields + SmallVector fields; + for (auto f : D->fields()) { + fields.push_back(f); + } + + fields = rearrange(*this, fields); // This will rebuild the Decl chain of fields D->reorderFields(fields); } - // FIXME end Randstruct code if (isMsLayout(*this)) { MicrosoftRecordLayoutBuilder Builder(*this); From 73325c971f0338e9a712ecce6cc5c57fa0a56867 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Fri, 15 Feb 2019 20:47:55 +0000 Subject: [PATCH 12/87] Delete hacky reorderFields method --- clang/include/clang/AST/Decl.h | 2 -- clang/lib/AST/Decl.cpp | 8 -------- clang/lib/AST/RecordLayoutBuilder.cpp | 10 ---------- 3 files changed, 20 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 0f201aaa979a7e..933166691a0145 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3814,8 +3814,6 @@ class RecordDecl : public TagDecl { /// nullptr is returned if no named data member exists. const FieldDecl *findFirstNamedDataMember() const; - void reorderFields(ArrayRef Decls) const; - private: /// Deserialize just the fields. void LoadFieldsFromExternalStorage() const; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 520a0891973adc..98962461a7e1f8 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4148,14 +4148,6 @@ RecordDecl::field_iterator RecordDecl::field_begin() const { return field_iterator(decl_iterator(FirstDecl)); } -void RecordDecl::reorderFields(ArrayRef Decls) const { - Decl *NewFirst, *NewLast; - std::tie(NewFirst, NewLast) = - BuildDeclChain(Decls, false); - FirstDecl = NewFirst; - LastDecl = NewLast; -} - /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 57cea368d1f308..d5a177ecacd4e6 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2989,16 +2989,6 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { - // A staging area to easily reorder the fields - SmallVector fields; - for (auto f : D->fields()) { - fields.push_back(f); - } - - fields = rearrange(*this, fields); - - // This will rebuild the Decl chain of fields - D->reorderFields(fields); } if (isMsLayout(*this)) { From 456bd5a6f5617eb8a0ca7399f3655d8876b9549c Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 18 Feb 2019 18:26:07 -0800 Subject: [PATCH 13/87] WIP, first attempt at emitting compiler warning --- .../include/clang/Basic/DiagnosticASTKinds.td | 6 +++++ clang/lib/AST/RecordLayoutBuilder.cpp | 25 +++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index c2a390fa465d81..ceee1b34fcd703 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -343,4 +343,10 @@ def warn_padded_struct_size : Warning< InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; + +// RandStruct implementation +def warn_randomize_attr_conflict : Warning< + "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes. " + "attribute 'no_randomize_layout' takes precedence ">; + } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 57cea368d1f308..f7cf95d692b865 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2986,19 +2986,24 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (Entry) return *Entry; const ASTRecordLayout *NewEntry = nullptr; - + bool ShouldBeRandomized = D->getAttr() != nullptr; - if (ShouldBeRandomized) { - // A staging area to easily reorder the fields - SmallVector fields; - for (auto f : D->fields()) { - fields.push_back(f); - } + bool NotToBeRandomized = D->getAttr() != nullptr; + + if (ShouldBeRandomized && NotToBeRandomized) { + Diag(D->getLocation(), diag::warn_randomize_attr_conflict); + } + else if (ShouldBeRandomized) { + // A staging area to easily reorder the fields + SmallVector fields; + for (auto f : D->fields()) { + fields.push_back(f); + } - fields = rearrange(*this, fields); + fields = rearrange(*this, fields); - // This will rebuild the Decl chain of fields - D->reorderFields(fields); + // This will rebuild the Decl chain of fields + D->reorderFields(fields); } if (isMsLayout(*this)) { From 16160e3f76f827e6b3a556f7436bc56d7426b384 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Tue, 19 Feb 2019 04:10:03 +0000 Subject: [PATCH 14/87] Refactor code into tidier classes New changes: * RecordFieldOrganizer is an interface that can be used to manipulate a RecordDecl's field order. * RecordFieldOrganizer is a "friend" to the DeclContext (which maintains the linked list) * The Randstruct class is a subclass that performs cache friendly randomization --- clang/include/clang/AST/Decl.h | 1 + clang/include/clang/AST/DeclBase.h | 2 + .../clang/AST/RecordFieldReorganizer.h | 47 ++++++++++++++ clang/lib/AST/CMakeLists.txt | 2 +- clang/lib/AST/LayoutFieldRandomizer.h | 27 -------- ...domizer.cpp => RecordFieldReorganizer.cpp} | 64 +++++++++++++++---- clang/lib/AST/RecordLayoutBuilder.cpp | 4 +- 7 files changed, 104 insertions(+), 43 deletions(-) create mode 100644 clang/include/clang/AST/RecordFieldReorganizer.h delete mode 100644 clang/lib/AST/LayoutFieldRandomizer.h rename clang/lib/AST/{LayoutFieldRandomizer.cpp => RecordFieldReorganizer.cpp} (76%) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 933166691a0145..9d7eaf11d0e115 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -65,6 +65,7 @@ class Module; class NamespaceDecl; class ParmVarDecl; class RecordDecl; +class RecordFieldReorganizer; class Stmt; class StringLiteral; class TagDecl; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 9117f53487d65b..2cc1b483aaa344 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1270,6 +1270,8 @@ class DeclContext { friend class ExternalASTSource; /// For CreateStoredDeclsMap friend class DependentDiagnostic; + /// For fine-grained control of field order + friend class RecordFieldReorganizer; /// For hasNeedToReconcileExternalVisibleStorage, /// hasLazyLocalLexicalLookups, hasLazyExternalLexicalLookups friend class ASTWriter; diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h new file mode 100644 index 00000000000000..1f2562b5e389cd --- /dev/null +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -0,0 +1,47 @@ +//===-- RecordFieldReorganizer.h - Interface for manipulating field order --*- +// C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header file contains the base class that defines an interface for +// manipulating a RecordDecl's field layouts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_AST_RECORDFIELDREORGANIZER_H +#define LLVM_CLANG_LIB_AST_RECORDFIELDREORGANIZER_H + +#include "Decl.h" + +namespace clang { + +// FIXME: Find a better alternative to SmallVector with hardcoded size! + +class RecordFieldReorganizer { +public: + virtual ~RecordFieldReorganizer() = default; + void reorganizeFields(const ASTContext &C, const RecordDecl *D) const; + +protected: + virtual void reorganize(const ASTContext &C, const RecordDecl *D, + SmallVector &NewOrder) const = 0; + +private: + void commit(const RecordDecl *D, + SmallVectorImpl &NewFieldOrder) const; +}; + +class Randstruct : public RecordFieldReorganizer { +protected: + virtual void reorganize(const ASTContext &C, const RecordDecl *D, + SmallVector &NewOrder) const override; +}; + +} // namespace clang + +#endif diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index ad9f283be48657..08acf687971957 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -44,7 +44,7 @@ add_clang_library(clangAST InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp - LayoutFieldRandomizer.cpp + RecordFieldReorganizer.cpp Mangle.cpp MicrosoftCXXABI.cpp MicrosoftMangle.cpp diff --git a/clang/lib/AST/LayoutFieldRandomizer.h b/clang/lib/AST/LayoutFieldRandomizer.h deleted file mode 100644 index 81af1612b39e98..00000000000000 --- a/clang/lib/AST/LayoutFieldRandomizer.h +++ /dev/null @@ -1,27 +0,0 @@ -//===----- LayoutFieldRandomizer.h - Entry Point for Randstruct --*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This header file provides the entry point for the Randstruct structure -// layout randomization code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_AST_LAYOUTFIELDRANDOMIZER_H -#define LLVM_CLANG_LIB_AST_LAYOUTFIELDRANDOMIZER_H - -#include "clang/AST/AST.h" - -namespace clang { -/// Rearranges the order of the supplied fields. Will make best effort to fit -// members into a cache line. -SmallVector rearrange(const ASTContext &ctx, - SmallVector fields); -} // namespace clang - -#endif diff --git a/clang/lib/AST/LayoutFieldRandomizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp similarity index 76% rename from clang/lib/AST/LayoutFieldRandomizer.cpp rename to clang/lib/AST/RecordFieldReorganizer.cpp index 1ec73e71923b38..4a4d8c60e55d91 100644 --- a/clang/lib/AST/LayoutFieldRandomizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -1,4 +1,4 @@ -//===----- LayoutFieldRandomizer.cpp - Randstruct Implementation -*- C++ +//===----- RecordFieldReorganizer.cpp - Implementation for field reorder -*- C++ //-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -7,20 +7,59 @@ // //===----------------------------------------------------------------------===// // -// Cache line best-effort field randomization +// Contains the implementation for RecordDecl field reordering. // //===----------------------------------------------------------------------===// -#include "LayoutFieldRandomizer.h" -#include "llvm/ADT/SmallVector.h" +#include "clang/AST/RecordFieldReorganizer.h" +#include "clang/AST/ASTContext.h" #include #include #include +#include #include +// FIXME: Find a better alternative to SmallVector with hardcoded size! + namespace clang { +void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, + const RecordDecl *D) const { + // Save original fields for asserting later that a subclass hasn't + // sabotaged the RecordDecl by removing or adding fields + std::set mutateGuard; + + SmallVector fields; + for (auto f : D->fields()) { + mutateGuard.insert(f); + fields.push_back(f); + } + + // Now allow subclass implementations to reorder the fields + reorganize(C, D, fields); + + // Assert all fields are still present + assert(mutateGuard.size() == fields.size() && + "Field count altered after reorganization"); + for (auto f : fields) { + auto found = std::find(std::begin(mutateGuard), std::end(mutateGuard), f); + assert(found != std::end(mutateGuard) && + "Unknown field encountered after reorganization"); + } + + commit(D, fields); +} + +void RecordFieldReorganizer::commit( + const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const { + Decl *First, *Last; + std::tie(First, Last) = DeclContext::BuildDeclChain( + NewFieldOrder, D->hasLoadedFieldsFromExternalStorage()); + D->FirstDecl = First; + D->LastDecl = Last; +} + /// Bucket to store fields up to size of a cache line during randomization. class Bucket { public: @@ -51,11 +90,11 @@ class BitfieldRun : public Bucket { virtual bool isBitfieldRun() const override; }; -// TODO: Is there a way to detect this? (i.e. on 32bit system vs 64?) +// FIXME: Is there a way to detect this? (i.e. on 32bit system vs 64?) const size_t CACHE_LINE = 64; SmallVector Bucket::randomize() { - // TODO use seed + // FIXME use seed auto rng = std::default_random_engine{}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; @@ -100,10 +139,7 @@ bool BitfieldRun::canFit(size_t size) const { return true; } -bool BitfieldRun::isBitfieldRun() const { - // Yes. - return true; -} +bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector randomize(SmallVector fields) { auto rng = std::default_random_engine{}; @@ -161,7 +197,6 @@ SmallVector perfrandomize(const ASTContext &ctx, currentBucket = llvm::make_unique(); } - // FIXME get access to AST Context auto width = ctx.getTypeInfo(f->getType()).Width; // If we can fit, add it. @@ -209,9 +244,10 @@ SmallVector perfrandomize(const ASTContext &ctx, return finalOrder; } -SmallVector rearrange(const ASTContext &ctx, - SmallVector fields) { - return perfrandomize(ctx, fields); +void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, + SmallVector &NewOrder) const { + SmallVector randomized = perfrandomize(C, NewOrder); + NewOrder = randomized; } } // namespace clang diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index d5a177ecacd4e6..2cf5066e921b33 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "LayoutFieldRandomizer.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -16,6 +15,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/RecordFieldReorganizer.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Format.h" @@ -2989,6 +2989,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { + Randstruct randstruct; + randstruct.reorganizeFields(*this, D); } if (isMsLayout(*this)) { From b1f11a30c60c046dc050b4bdc978d034b8db30a5 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 18 Feb 2019 20:26:28 -0800 Subject: [PATCH 15/87] Added declaration of Diagnostic(), receiving errors. --- clang/lib/AST/RecordLayoutBuilder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f7cf95d692b865..30e1e82a435491 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2971,6 +2971,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // not a complete definition (which is what isDefinition() tests) // until we *finish* parsing the definition. + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + if (D->hasExternalLexicalStorage() && !D->getDefinition()) getExternalSource()->CompleteType(const_cast(D)); @@ -2989,7 +2991,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; bool NotToBeRandomized = D->getAttr() != nullptr; - + if (ShouldBeRandomized && NotToBeRandomized) { Diag(D->getLocation(), diag::warn_randomize_attr_conflict); } From dee16c7001451207aa2cb26242eed7d70238d3da Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Tue, 19 Feb 2019 21:51:37 -0800 Subject: [PATCH 16/87] builds, but cannot compile. Cant find stdio.h --- clang/lib/AST/RecordLayoutBuilder.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 30e1e82a435491..8e45713a09ed7d 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2971,8 +2971,6 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // not a complete definition (which is what isDefinition() tests) // until we *finish* parsing the definition. - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); - if (D->hasExternalLexicalStorage() && !D->getDefinition()) getExternalSource()->CompleteType(const_cast(D)); @@ -2993,7 +2991,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool NotToBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized && NotToBeRandomized) { - Diag(D->getLocation(), diag::warn_randomize_attr_conflict); + //Diag(D->getLocation(), diag::warn_randomize_attr_conflict); + getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_conflict); } else if (ShouldBeRandomized) { // A staging area to easily reorder the fields From 063f1b141bf25ec31dbaeb6aa33fb967c1ef089f Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 11 Feb 2019 19:39:18 -0800 Subject: [PATCH 17/87] Added the 'no_randomize_layout' attr to clang --- clang/include/clang/Basic/Attr.td | 7 +++++++ clang/lib/Sema/SemaDeclAttr.cpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 6b3ec95ce91490..4cde6982dbadd4 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3208,3 +3208,10 @@ def RandomizeLayout : InheritableAttr { let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; } + +def NoRandomizeLayout : InheritableAttr { + let Spellings = [GCC<"no_randomize_layout">, Declspec<"no_randomize_layout">, + Keyword<"no_randomize_layout">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d1f0513da1219f..60aa1fa3457e57 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6856,6 +6856,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_RandomizeLayout: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_NoRandomizeLayout: + handleSimpleAttribute(S, D, AL); + break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; From 938b5cfea79cd6b11c8cd4d90b6f19e1959a41b8 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 18 Feb 2019 18:26:07 -0800 Subject: [PATCH 18/87] WIP, first attempt at emitting compiler warning --- .../include/clang/Basic/DiagnosticASTKinds.td | 6 ++++++ clang/lib/AST/RecordLayoutBuilder.cpp | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index c2a390fa465d81..ceee1b34fcd703 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -343,4 +343,10 @@ def warn_padded_struct_size : Warning< InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; + +// RandStruct implementation +def warn_randomize_attr_conflict : Warning< + "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes. " + "attribute 'no_randomize_layout' takes precedence ">; + } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 6c69b91ef75e2a..18cc8d26fd96aa 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2986,11 +2986,27 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (Entry) return *Entry; const ASTRecordLayout *NewEntry = nullptr; - + bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { Randstruct randstruct; randstruct.reorganizeFields(*this, D); + bool NotToBeRandomized = D->getAttr() != nullptr; + + if (ShouldBeRandomized && NotToBeRandomized) { + Diag(D->getLocation(), diag::warn_randomize_attr_conflict); + } + else if (ShouldBeRandomized) { + // A staging area to easily reorder the fields + SmallVector fields; + for (auto f : D->fields()) { + fields.push_back(f); + } + + fields = rearrange(*this, fields); + + // This will rebuild the Decl chain of fields + D->reorderFields(fields); } if (isMsLayout(*this)) { From e1af06f81303ceff7a0680c32692a10ca895e9cf Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 18 Feb 2019 20:26:28 -0800 Subject: [PATCH 19/87] Added declaration of Diagnostic(), receiving errors. --- clang/lib/AST/RecordLayoutBuilder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 18cc8d26fd96aa..b67101a7595a26 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2971,6 +2971,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // not a complete definition (which is what isDefinition() tests) // until we *finish* parsing the definition. + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + if (D->hasExternalLexicalStorage() && !D->getDefinition()) getExternalSource()->CompleteType(const_cast(D)); @@ -2992,7 +2994,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Randstruct randstruct; randstruct.reorganizeFields(*this, D); bool NotToBeRandomized = D->getAttr() != nullptr; - + if (ShouldBeRandomized && NotToBeRandomized) { Diag(D->getLocation(), diag::warn_randomize_attr_conflict); } From a4a855d4a4b2b8360c884b82a8d3ca034395134c Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Tue, 19 Feb 2019 21:51:37 -0800 Subject: [PATCH 20/87] builds, but cannot compile. Cant find stdio.h --- clang/lib/AST/RecordLayoutBuilder.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index b67101a7595a26..fe5602b3a4d671 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2971,8 +2971,6 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // not a complete definition (which is what isDefinition() tests) // until we *finish* parsing the definition. - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); - if (D->hasExternalLexicalStorage() && !D->getDefinition()) getExternalSource()->CompleteType(const_cast(D)); @@ -2996,7 +2994,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool NotToBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized && NotToBeRandomized) { - Diag(D->getLocation(), diag::warn_randomize_attr_conflict); + //Diag(D->getLocation(), diag::warn_randomize_attr_conflict); + getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_conflict); } else if (ShouldBeRandomized) { // A staging area to easily reorder the fields From 11d18d7eafd4b71cbfcb249c206c8587605a64b7 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Thu, 21 Feb 2019 19:09:33 +0000 Subject: [PATCH 21/87] putting RandstructSeed in Decl.h --- clang/include/clang/AST/Decl.h | 1 + clang/include/clang/AST/RecordFieldReorganizer.h | 5 +++++ clang/include/clang/Driver/Options.td | 1 + clang/lib/AST/RecordFieldReorganizer.cpp | 16 +++++++++++++--- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 7 +++++++ clang/lib/Driver/ToolChains/Clang.h | 1 + clang/lib/Frontend/CompilerInvocation.cpp | 7 +++++++ 8 files changed, 36 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 0f6c660e698b09..df6600f48aeffb 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -76,6 +76,7 @@ class TypeAliasTemplateDecl; class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; +extern std::string RandstructSeed; /// A container of type source information. /// diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 1f2562b5e389cd..3768d5baeef92f 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -19,11 +19,13 @@ #include "Decl.h" namespace clang { + //std::string RandstructSeed; // FIXME: Find a better alternative to SmallVector with hardcoded size! class RecordFieldReorganizer { public: + RecordFieldReorganizer(std::string seed); virtual ~RecordFieldReorganizer() = default; void reorganizeFields(const ASTContext &C, const RecordDecl *D) const; @@ -32,11 +34,14 @@ class RecordFieldReorganizer { SmallVector &NewOrder) const = 0; private: + std::string RandomSeed; void commit(const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const; }; class Randstruct : public RecordFieldReorganizer { +public: + Randstruct(std::string seed); protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 57050412ab5dc2..cb7efbf3edd474 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1258,6 +1258,7 @@ def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">; def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group; +def frandstruct_seed_EQ : Joined<["-"], "frandstruct-seed=">, Group; def fms_extensions : Flag<["-"], "fms-extensions">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group, Flags<[CC1Option, CoreOption]>, diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 4a4d8c60e55d91..374a83753c1281 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -24,6 +24,13 @@ namespace clang { + +RecordFieldReorganizer::RecordFieldReorganizer(std::string seed) { + RandomSeed = seed; +} + +Randstruct::Randstruct(std::string seed) : RecordFieldReorganizer(seed) {}; + void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, const RecordDecl *D) const { // Save original fields for asserting later that a subclass hasn't @@ -95,7 +102,8 @@ const size_t CACHE_LINE = 64; SmallVector Bucket::randomize() { // FIXME use seed - auto rng = std::default_random_engine{}; + std::seed_seq Seq(clang::RandstructSeed.begin(), clang::RandstructSeed.end()); + auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } @@ -142,7 +150,8 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector randomize(SmallVector fields) { - auto rng = std::default_random_engine{}; + std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); + auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } @@ -231,7 +240,8 @@ SmallVector perfrandomize(const ASTContext &ctx, buckets.push_back(std::move(currentBitfieldRun)); } - auto rng = std::default_random_engine{}; + std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); + auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(buckets), std::end(buckets), rng); // Produce the new ordering of the elements from our buckets. diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 6c69b91ef75e2a..04c38002b6dc43 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2989,7 +2989,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { - Randstruct randstruct; + Randstruct randstruct(RandstructSeed); randstruct.reorganizeFields(*this, D); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index e7fb3fe403c564..bc93beb268046a 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4405,6 +4405,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine(N))); } + // -frandstruct-seed + if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { + //CmdArgs.push_back(A->getValue()); + std::string mystr = A->getValue(); + clang::RandstructSeed = mystr; + } + // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index 81d8a351443b10..cf3ff3f0e48572 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -19,6 +19,7 @@ #include "llvm/Support/raw_ostream.h" namespace clang { +extern std::string RandstructSeed; class ObjCRuntime; namespace driver { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 1a33a00004d606..f3c7a796e8e917 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -91,6 +91,9 @@ #include #include +namespace clang { + std::string RandstructSeed; +} using namespace clang; using namespace driver; using namespace options; @@ -114,6 +117,7 @@ CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} CompilerInvocationBase::~CompilerInvocationBase() = default; +//std::string RandstructSeed; //===----------------------------------------------------------------------===// // Deserialization (from args) @@ -1669,6 +1673,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); } + if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed_EQ)) { + clang::RandstructSeed = A->getValue(); + } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); From d76e98b0a8026300abce001fbe712273fafaf425 Mon Sep 17 00:00:00 2001 From: Tim Pugh Date: Thu, 21 Feb 2019 21:30:53 +0000 Subject: [PATCH 22/87] RandomizeLayout identification for regression test This commit is to resolve the identification of the RandomizeLayout attribute to the regression test suite. Without this, running "make clang-test" will result in a failure due to it identifying an attribute but not having it included in ../clang/test/Misc/pragma-attribute-supported-attributes-list.test. This protects against the addition/removal of attributes. --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 45012ae9bfdd11..8915de50f668dc 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -117,6 +117,7 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) From 3deff8803cbb521cc5786682708c12ca624260bd Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Thu, 21 Feb 2019 21:35:14 +0000 Subject: [PATCH 23/87] remove RandstructSeed declaration from Decl.h --- clang/include/clang/AST/Decl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index df6600f48aeffb..0f6c660e698b09 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -76,7 +76,6 @@ class TypeAliasTemplateDecl; class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; -extern std::string RandstructSeed; /// A container of type source information. /// From 753b226189a0ffd66cd0f785d16fe1110b35fda4 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Thu, 21 Feb 2019 23:08:45 +0000 Subject: [PATCH 24/87] Revert commit so it may be introduced by PR This reverts commit d76e98b0a8026300abce001fbe712273fafaf425. --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 8915de50f668dc..45012ae9bfdd11 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -117,7 +117,6 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) From 69c348e2cfc0b53ae5c5251defb7666cd53fb7b9 Mon Sep 17 00:00:00 2001 From: Tim Pugh Date: Thu, 21 Feb 2019 21:30:53 +0000 Subject: [PATCH 25/87] RandomizeLayout identification for regression test This commit is to resolve the identification of the RandomizeLayout attribute to the regression test suite. Without this, running "make clang-test" will result in a failure due to it identifying an attribute but not having it included in: ../clang/test/Misc/pragma-attribute-supported-attributes-list.test. This protects against the addition/removal of attributes. --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 45012ae9bfdd11..8915de50f668dc 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -117,6 +117,7 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) From 5e9c123191e290cdd05d29cdb159c157731a7d8d Mon Sep 17 00:00:00 2001 From: Tim Pugh Date: Thu, 21 Feb 2019 21:30:53 +0000 Subject: [PATCH 26/87] RandomizeLayout identification for regression test This commit is to resolve the identification of the RandomizeLayout attribute to the regression test suite. Without this, running "make clang-test" will result in a failure due to it identifying an attribute but not having it included in: ../clang/test/Misc/pragma-attribute-supported-attributes-list.test. This protects against the addition/removal of attributes. Co-authored-by:Nikk --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 45012ae9bfdd11..8915de50f668dc 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -117,6 +117,7 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) From 162bda5567f785104a833fb54e8ca1c650d4fe23 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Fri, 22 Feb 2019 02:55:21 +0000 Subject: [PATCH 27/87] value not being saved in global --- clang/include/clang/AST/RandstructSeed.h | 5 +++++ clang/include/clang/AST/RecordFieldReorganizer.h | 2 -- clang/lib/AST/RecordFieldReorganizer.cpp | 7 ++++++- clang/lib/AST/RecordLayoutBuilder.cpp | 2 ++ clang/lib/Driver/ToolChains/Clang.cpp | 8 ++++++-- clang/lib/Driver/ToolChains/Clang.h | 1 - clang/lib/Frontend/CompilerInvocation.cpp | 8 +++----- errs | 1 + 8 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 clang/include/clang/AST/RandstructSeed.h create mode 100644 errs diff --git a/clang/include/clang/AST/RandstructSeed.h b/clang/include/clang/AST/RandstructSeed.h new file mode 100644 index 00000000000000..5b9bac6a9c2ac3 --- /dev/null +++ b/clang/include/clang/AST/RandstructSeed.h @@ -0,0 +1,5 @@ +#ifndef RANDSTRUCTSEED_H +#define RANDSTRUCTSEED_H +#include +extern std::string RandstructSeed; +#endif diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 3768d5baeef92f..6f46d2f587ba02 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -19,8 +19,6 @@ #include "Decl.h" namespace clang { - //std::string RandstructSeed; - // FIXME: Find a better alternative to SmallVector with hardcoded size! class RecordFieldReorganizer { diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 374a83753c1281..02ae8a8b3cf6b9 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -13,6 +13,7 @@ #include "clang/AST/RecordFieldReorganizer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RandstructSeed.h" #include #include @@ -102,7 +103,9 @@ const size_t CACHE_LINE = 64; SmallVector Bucket::randomize() { // FIXME use seed - std::seed_seq Seq(clang::RandstructSeed.begin(), clang::RandstructSeed.end()); + llvm::errs() << "Bucket::randomize(); " << ::RandstructSeed << " at " << &RandstructSeed << " \n"; + //llvm::errs() << "I am Bucket::randomize() and RandomSeed is " << RandomSeed << "\n"; + std::seed_seq Seq(::RandstructSeed.begin(), ::RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; @@ -150,6 +153,7 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector randomize(SmallVector fields) { + llvm::errs() << "randomize(); " << RandstructSeed << " at " << &RandstructSeed << "\n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); @@ -240,6 +244,7 @@ SmallVector perfrandomize(const ASTContext &ctx, buckets.push_back(std::move(currentBitfieldRun)); } + llvm::errs() << "perfrandomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(buckets), std::end(buckets), rng); diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 04c38002b6dc43..489c942089abd2 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/RandstructSeed.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -2989,6 +2990,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { + llvm::errs() << "ShouldBeRandomized; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; Randstruct randstruct(RandstructSeed); randstruct.reorganizeFields(*this, D); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index bc93beb268046a..812993f34d6f72 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/RandstructSeed.h" #include "Clang.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" @@ -50,6 +51,8 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +std::string RandstructSeed = "initialseedstring"; + static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC)) { @@ -4408,8 +4411,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { //CmdArgs.push_back(A->getValue()); - std::string mystr = A->getValue(); - clang::RandstructSeed = mystr; + llvm::errs() << "I am handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; + RandstructSeed = A->getValue(0); + llvm::errs() << "I am handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; } // -fvisibility= and -fvisibility-ms-compat are of a piece. diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index cf3ff3f0e48572..81d8a351443b10 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -19,7 +19,6 @@ #include "llvm/Support/raw_ostream.h" namespace clang { -extern std::string RandstructSeed; class ObjCRuntime; namespace driver { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f3c7a796e8e917..bf7b7d854fdd32 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/RandstructSeed.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" @@ -91,9 +92,6 @@ #include #include -namespace clang { - std::string RandstructSeed; -} using namespace clang; using namespace driver; using namespace options; @@ -117,7 +115,6 @@ CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} CompilerInvocationBase::~CompilerInvocationBase() = default; -//std::string RandstructSeed; //===----------------------------------------------------------------------===// // Deserialization (from args) @@ -1674,7 +1671,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ActionName = A->getValue(); } if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed_EQ)) { - clang::RandstructSeed = A->getValue(); + llvm::errs() << "ParseFrontendArgs; " << RandstructSeed << "\n"; + RandstructSeed = A->getValue(); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) diff --git a/errs b/errs new file mode 100644 index 00000000000000..33edf65aab6e7a --- /dev/null +++ b/errs @@ -0,0 +1 @@ +make: *** No targets specified and no makefile found. Stop. From 97bb5ce9c37fd65ad8134b61fc207d07e798e3dc Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Fri, 22 Feb 2019 03:08:02 +0000 Subject: [PATCH 28/87] removing unused coede --- clang/include/clang/AST/RecordFieldReorganizer.h | 5 +---- clang/lib/AST/RecordFieldReorganizer.cpp | 7 ------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 6f46d2f587ba02..1f2562b5e389cd 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -19,11 +19,11 @@ #include "Decl.h" namespace clang { + // FIXME: Find a better alternative to SmallVector with hardcoded size! class RecordFieldReorganizer { public: - RecordFieldReorganizer(std::string seed); virtual ~RecordFieldReorganizer() = default; void reorganizeFields(const ASTContext &C, const RecordDecl *D) const; @@ -32,14 +32,11 @@ class RecordFieldReorganizer { SmallVector &NewOrder) const = 0; private: - std::string RandomSeed; void commit(const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const; }; class Randstruct : public RecordFieldReorganizer { -public: - Randstruct(std::string seed); protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 02ae8a8b3cf6b9..0a0a98ec9b0940 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -25,13 +25,6 @@ namespace clang { - -RecordFieldReorganizer::RecordFieldReorganizer(std::string seed) { - RandomSeed = seed; -} - -Randstruct::Randstruct(std::string seed) : RecordFieldReorganizer(seed) {}; - void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, const RecordDecl *D) const { // Save original fields for asserting later that a subclass hasn't From 6ef63ebff3553275beb9af390bd052d75a6d9edb Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Fri, 22 Feb 2019 03:31:14 +0000 Subject: [PATCH 29/87] removing randstruct constructor call --- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 489c942089abd2..4cb5511d781975 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2991,7 +2991,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { llvm::errs() << "ShouldBeRandomized; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; - Randstruct randstruct(RandstructSeed); + Randstruct randstruct; randstruct.reorganizeFields(*this, D); } From e0cfd8aae3595513576ea442d0975bd6803f575c Mon Sep 17 00:00:00 2001 From: James Foster Date: Sat, 23 Feb 2019 00:37:29 +0000 Subject: [PATCH 30/87] Added basic implementation of auto selection for strucutres of only function pointers --- .../clang/AST/RecordFieldReorganizer.h | 1 + clang/lib/AST/RecordFieldReorganizer.cpp | 21 +++++++++++++++++-- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 1f2562b5e389cd..7f15e1b3b10ed5 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -34,6 +34,7 @@ class RecordFieldReorganizer { private: void commit(const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const; + bool autostructselect(const SmallVector fields) const; }; class Randstruct : public RecordFieldReorganizer { diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 4a4d8c60e55d91..0190acd50c922f 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -35,7 +35,11 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, mutateGuard.insert(f); fields.push_back(f); } - + if(D->getAttr() == nullptr){ + if(!autostructselect(fields)){ + return; + } + } // Now allow subclass implementations to reorder the fields reorganize(C, D, fields); @@ -50,7 +54,20 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, commit(D, fields); } - +bool RecordFieldReorganizer::autostructselect(const SmallVector fields) const { + + bool Select = true; + for (auto f : fields){ + auto t = f->getFunctionType(); + auto s = ((FieldDecl *)f)->getNameAsString(); + llvm::errs() << "Function " << s << " type: " << t << "\n"; + if(t == nullptr){ + Select = false; + break; + } + } + return Select; +} void RecordFieldReorganizer::commit( const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const { Decl *First, *Last; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 6c69b91ef75e2a..8f8b3671214b36 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2988,7 +2988,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; bool ShouldBeRandomized = D->getAttr() != nullptr; - if (ShouldBeRandomized) { + if (true) { Randstruct randstruct; randstruct.reorganizeFields(*this, D); } From 9d3845ec7fcc5a586119e29c03155543ae180419 Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 22 Feb 2019 17:07:13 -0800 Subject: [PATCH 31/87] Clean up PR PR was slightly behind, update and fix punctuation --- clang/include/clang/Basic/DiagnosticASTKinds.td | 4 ++-- clang/lib/AST/RecordLayoutBuilder.cpp | 16 ++-------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index ceee1b34fcd703..710a88a832e7b1 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -346,7 +346,7 @@ def warn_unnecessary_packed : Warning< // RandStruct implementation def warn_randomize_attr_conflict : Warning< - "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes. " - "attribute 'no_randomize_layout' takes precedence ">; + "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes;" + "attribute 'no_randomize_layout' takes precedence">; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index fe5602b3a4d671..cff5578c6a2cf1 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2988,26 +2988,14 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; bool ShouldBeRandomized = D->getAttr() != nullptr; - if (ShouldBeRandomized) { - Randstruct randstruct; - randstruct.reorganizeFields(*this, D); bool NotToBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized && NotToBeRandomized) { - //Diag(D->getLocation(), diag::warn_randomize_attr_conflict); getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_conflict); } else if (ShouldBeRandomized) { - // A staging area to easily reorder the fields - SmallVector fields; - for (auto f : D->fields()) { - fields.push_back(f); - } - - fields = rearrange(*this, fields); - - // This will rebuild the Decl chain of fields - D->reorderFields(fields); + Randstruct randstruct; + randstruct.reorganizeFields(*this,D); } if (isMsLayout(*this)) { From f94de0689a0218ed06322b6207b854b332835321 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Sat, 23 Feb 2019 05:56:15 +0000 Subject: [PATCH 32/87] Add DiagGroup to NoRandomizeLayout attribute All attributes that emit warnings are required to be members of a warning group; this is checked by the clang-test regression suite. --- clang/include/clang/Basic/DiagnosticASTKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 710a88a832e7b1..899b349ebcd7ed 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -347,6 +347,6 @@ def warn_unnecessary_packed : Warning< // RandStruct implementation def warn_randomize_attr_conflict : Warning< "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes;" - "attribute 'no_randomize_layout' takes precedence">; + "attribute 'no_randomize_layout' takes precedence">, InGroup>; } From fadd2474bf7519494a9fe0b016d970baaf755f65 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Sat, 23 Feb 2019 05:57:12 +0000 Subject: [PATCH 33/87] Add NoRandomizeLayout to supported attributes list All supported attributes must be etched in stone in the supported attributes regression test. --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 45012ae9bfdd11..828aad4a874ea5 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -80,6 +80,7 @@ // CHECK-NEXT: NoInstrumentFunction (SubjectMatchRule_function) // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function) // CHECK-NEXT: NoMips16 (SubjectMatchRule_function) +// CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) From ae1bf92d8b3231c154c1dd0ea7fd50c4a559f1bc Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Sat, 23 Feb 2019 06:00:13 +0000 Subject: [PATCH 34/87] Add space after semicolon in warning message --- clang/include/clang/Basic/DiagnosticASTKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 899b349ebcd7ed..412f3fd69bbbf2 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -346,7 +346,7 @@ def warn_unnecessary_packed : Warning< // RandStruct implementation def warn_randomize_attr_conflict : Warning< - "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes;" + "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes; " "attribute 'no_randomize_layout' takes precedence">, InGroup>; } From b3a2306aac054bb1e5bab9ae1888cbb2e7b4607a Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 10:49:16 -0800 Subject: [PATCH 35/87] test commit --- innocuous | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 innocuous diff --git a/innocuous b/innocuous new file mode 100644 index 00000000000000..e69de29bb2d1d6 From a9200c25b893a946c3a818f0ed47e04b7e6be125 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 18:51:03 +0000 Subject: [PATCH 36/87] printf debugging --- clang/include/clang/AST/RandstructSeed.h | 3 +++ clang/lib/AST/RecordFieldReorganizer.cpp | 7 +++++-- clang/lib/AST/RecordLayoutBuilder.cpp | 2 ++ clang/lib/CodeGen/CodeGenAction.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 12 ++++++++---- clang/lib/Frontend/CompilerInvocation.cpp | 4 +++- clang/lib/Frontend/FrontendAction.cpp | 1 + clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 1 + errs | 1 - gdbcommands | 8 ++++++++ innocuous | 0 notes | 12 ++++++++++++ 12 files changed, 44 insertions(+), 8 deletions(-) delete mode 100644 errs create mode 100644 gdbcommands delete mode 100644 innocuous create mode 100644 notes diff --git a/clang/include/clang/AST/RandstructSeed.h b/clang/include/clang/AST/RandstructSeed.h index 5b9bac6a9c2ac3..7257558ad7bbdd 100644 --- a/clang/include/clang/AST/RandstructSeed.h +++ b/clang/include/clang/AST/RandstructSeed.h @@ -1,5 +1,8 @@ #ifndef RANDSTRUCTSEED_H #define RANDSTRUCTSEED_H #include +namespace clang { extern std::string RandstructSeed; +extern char cstr[128]; +} #endif diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 0a0a98ec9b0940..ce0de82764f62e 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -24,6 +24,8 @@ // FIXME: Find a better alternative to SmallVector with hardcoded size! namespace clang { +std::string RandstructSeed = "someseed"; +char cstr[128]; void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, const RecordDecl *D) const { @@ -96,9 +98,10 @@ const size_t CACHE_LINE = 64; SmallVector Bucket::randomize() { // FIXME use seed - llvm::errs() << "Bucket::randomize(); " << ::RandstructSeed << " at " << &RandstructSeed << " \n"; + llvm::errs() << "Bucket::randomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << " \n"; + llvm::errs() << "Bucket::randomize(); cstr" << std::string(cstr) << " at " << cstr << " : " << std::string(cstr).size() << " \n"; //llvm::errs() << "I am Bucket::randomize() and RandomSeed is " << RandomSeed << "\n"; - std::seed_seq Seq(::RandstructSeed.begin(), ::RandstructSeed.end()); + std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 4cb5511d781975..a20d8a2f73a4ff 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -22,6 +22,8 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" +//std::string RandstructSeed = "myrandomseed"; + using namespace clang; namespace { diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 0b631f72e6e4a4..c034268fb78136 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -1043,6 +1043,7 @@ void CodeGenAction::ExecuteAction() { return; } + //llvm::errs() << "CodeGenAction::ExecuteAction(); " << std::string(cstr) << "\n"; // Otherwise follow the normal AST path. this->ASTFrontendAction::ExecuteAction(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 812993f34d6f72..a8bb840b598572 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -46,12 +46,13 @@ #include // For getuid(). #endif +//std::string RandstructSeed = "initialseedstring"; + using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; -std::string RandstructSeed = "initialseedstring"; static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = @@ -4411,10 +4412,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { //CmdArgs.push_back(A->getValue()); - llvm::errs() << "I am handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; - RandstructSeed = A->getValue(0); - llvm::errs() << "I am handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; + llvm::errs() << "handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; + RandstructSeed.assign(A->getValue(0)); + strcpy(cstr,A->getValue(0)); + llvm::errs() << "cstr: " << std::string(cstr) << "\n"; + llvm::errs() << "handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; } + llvm::errs() << "handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index bf7b7d854fdd32..f54861ae1342e9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/RandstructSeed.h" +//#include "clang/AST/RandstructSeed.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" @@ -1670,10 +1670,12 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); } +/* if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed_EQ)) { llvm::errs() << "ParseFrontendArgs; " << RandstructSeed << "\n"; RandstructSeed = A->getValue(); } +*/ Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 3392923380f33c..7de6427eb88548 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -931,6 +931,7 @@ bool FrontendAction::Execute() { llvm::TimeRegion Timer(CI.getFrontendTimer()); ExecuteAction(); } + //llvm::errs() << "FrontendAction::Execute(); " << std::string(cstr) << "\n"; else ExecuteAction(); // If we are supposed to rebuild the global module index, do so now unless diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index c226838786f092..4abd98f60bf28a 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -268,6 +268,7 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { std::unique_ptr Act(CreateFrontendAction(*Clang)); if (!Act) return false; + //llvm::errs() << "cstr: " << std::string(clang::cstr) << "\n"; bool Success = Clang->ExecuteAction(*Act); if (Clang->getFrontendOpts().DisableFree) llvm::BuryPointer(std::move(Act)); diff --git a/errs b/errs deleted file mode 100644 index 33edf65aab6e7a..00000000000000 --- a/errs +++ /dev/null @@ -1 +0,0 @@ -make: *** No targets specified and no makefile found. Stop. diff --git a/gdbcommands b/gdbcommands new file mode 100644 index 00000000000000..78f5f209fcd002 --- /dev/null +++ b/gdbcommands @@ -0,0 +1,8 @@ +set follow-fork-mode child +set print pretty on +break RandFieldReorganizer.cpp:103 +break RandFieldReorganizer.cpp:152 +break RandFieldReorganizer.cpp:159 +break CompilerInvocation.cpp:1673 +break Clang.cpp:4413 +break RecordLayoutBuild.cpp:2993 diff --git a/innocuous b/innocuous deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/notes b/notes new file mode 100644 index 00000000000000..f9b9b914c5b805 --- /dev/null +++ b/notes @@ -0,0 +1,12 @@ +Program.cpp:37 is the first location that doesn't see cstr +CompilerInvocation.cpp:1679 is next relevant location + +gdb: set logging on +gdb: set logging file filename + +Program.cpp:37 Execute() takes Args - where are they defined? + +Job.cpp:341 + auto Args = llvm::toStringRefArray(Argv.data()); + +class Command.Arguments From 5ceee39c287be187f508f7a421012db6c2ee3809 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 18:36:22 -0800 Subject: [PATCH 37/87] manually adding arg before executing --- clang/lib/Driver/Job.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 1af454f8889cd7..0facfff2f44333 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -338,6 +338,10 @@ int Command::Execute(ArrayRef> Redirects, Argv.push_back(nullptr); auto Args = llvm::toStringRefArray(Argv.data()); + if (!RandstructSeed.empty()) + { + Args.push_back("-frandstruct-seed=" + RandstructSeed); + } return llvm::sys::ExecuteAndWait( Executable, Args, Env, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); From 5dd2a4579e625ffeb749a3ed931f7ec2459e4862 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 18:43:01 -0800 Subject: [PATCH 38/87] adding include to job.cpp --- clang/lib/Driver/Job.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 0facfff2f44333..d03674d03c1b01 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "clang/AST/RandstructSeed.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" From 727291469c5edb4f1abb9744c91cb6bf15df2835 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Sat, 23 Feb 2019 18:44:06 -0800 Subject: [PATCH 39/87] First draft for attribute documentation --- clang/include/clang/Basic/AttrDocs.td | 50 ++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index dada1badcd3824..b2c1c7516145af 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4094,4 +4094,52 @@ Likewise, when applied to a strong local variable, that variable becomes ``const`` and is considered externally-retained. When compiled without ``-fobjc-arc``, this attribute is ignored. -}]; } +}]; +} + +def ClangRandstructDocs : Documentation { + let Category = DocCatVariable; + let Heading = "randomize_layout, no_randomize_layout"; + let Content = [{ +The attributes ``randomize_layout`` and ``no_randomize_layout`` can be applied +to a C struct or class(???). + +``randomize_layout`` instructs the compiler to randomize the memory location +of the member variables of the struct or class(???). Functions will not be +shuffled, unless in the event that the member is a function pointer, then it +will be shuffled as a normal member variable. + +Conversely, ``no_randomize_layout`` is used to indicate that if using the +Automatic Strucuture Selection feature of the Randstruct implementation, the +compiler should not shuffle the members of the struct. + +If in the event that a struct or class(???) is labeled with both attributes, +the compiler will emit a warning indicating that these two cannot be used on +the same struct of class(???). The default behavior in this case is to not +randomize the struct, as the attribute ``no_randomize_layout`` takes precedence +over ``randomize_layout``. + +.. code-block:: c + + // Indicates that this struct should be randomized by Randstruct implementation. + struct __attribute__((randomize_layout)) s { + char *a; + char *b; + char *c; + }; + + // Indicates that this struct should NOT be randomized by Randstruct implementation. + struct __attribute__((no_randomize_layout)) s { + char *a; + char *b; + char *c; + }; + + // Emits compiler warning. Struct is NOT randomized by Randstruct implementation. + struct __attribute__((randomize_layout)) __attribute__((no_randomize_layout)) s { + char *a; + char *b; + char *c; + }; +}]; +} From 76f2bd120244d512864045b7c2a19432ebc2a789 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 19:33:02 -0800 Subject: [PATCH 40/87] throwaway commit --- clang/lib/Driver/Job.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index d03674d03c1b01..f3cf9ef76b1025 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -341,7 +341,8 @@ int Command::Execute(ArrayRef> Redirects, auto Args = llvm::toStringRefArray(Argv.data()); if (!RandstructSeed.empty()) { - Args.push_back("-frandstruct-seed=" + RandstructSeed); + //Args.push_back("-frandstruct-seed=" + RandstructSeed); + Args.push_back("-frandstruct-seed=IAMASEED"); } return llvm::sys::ExecuteAndWait( Executable, Args, Env, Redirects, /*secondsToWait*/ 0, From c4863cc3ae7cf295d9c27446180a9833c62b59f3 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 21:11:15 -0800 Subject: [PATCH 41/87] more printf debugging --- clang/lib/Frontend/CompilerInvocation.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f54861ae1342e9..153a6853d6317b 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1670,12 +1670,11 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); } -/* if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed_EQ)) { llvm::errs() << "ParseFrontendArgs; " << RandstructSeed << "\n"; - RandstructSeed = A->getValue(); + RandstructSeed = A->getValue(0); + strcpy(cstr, A->getValue(0).c_str()); } -*/ Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); From 1dbbe31a48df4bbe3bd5bc4518dd95fa938ead20 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 21:22:53 -0800 Subject: [PATCH 42/87] even more printf debugging --- clang/lib/Frontend/CompilerInvocation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 153a6853d6317b..d2b7dbe5306ff9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -//#include "clang/AST/RandstructSeed.h" +#include "clang/AST/RandstructSeed.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" @@ -1673,7 +1673,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed_EQ)) { llvm::errs() << "ParseFrontendArgs; " << RandstructSeed << "\n"; RandstructSeed = A->getValue(0); - strcpy(cstr, A->getValue(0).c_str()); + strcpy(cstr, A->getValue(0)); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) From 09a54e97a2cc9d6e187e8291701aa4e9a4f63156 Mon Sep 17 00:00:00 2001 From: jeff Date: Sat, 23 Feb 2019 22:37:02 -0800 Subject: [PATCH 43/87] Edit ClangRandstruct entry in AttrDocs.td --- clang/include/clang/Basic/AttrDocs.td | 34 +++++++++++++-------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b2c1c7516145af..24a48ed68c2398 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4102,44 +4102,42 @@ def ClangRandstructDocs : Documentation { let Heading = "randomize_layout, no_randomize_layout"; let Content = [{ The attributes ``randomize_layout`` and ``no_randomize_layout`` can be applied -to a C struct or class(???). +to a record. -``randomize_layout`` instructs the compiler to randomize the memory location -of the member variables of the struct or class(???). Functions will not be -shuffled, unless in the event that the member is a function pointer, then it -will be shuffled as a normal member variable. +``randomize_layout`` instructs the compiler to randomize the memory layout +of the member variables of the record. Conversely, ``no_randomize_layout`` is used to indicate that if using the -Automatic Strucuture Selection feature of the Randstruct implementation, the -compiler should not shuffle the members of the struct. +automatic strucuture selection feature of the Randstruct implementation, the +compiler should not shuffle the members of the record. -If in the event that a struct or class(???) is labeled with both attributes, -the compiler will emit a warning indicating that these two cannot be used on -the same struct of class(???). The default behavior in this case is to not -randomize the struct, as the attribute ``no_randomize_layout`` takes precedence -over ``randomize_layout``. +In the event that a record is labeled with both attributes, the compiler will +emit a warning indicating that these two cannot be used on the same record. +The default behavior in this case is to not randomize the struct, as the +attribute ``no_randomize_layout`` takes precedence over ``randomize_layout``. +This is implementation defined behavior. .. code-block:: c // Indicates that this struct should be randomized by Randstruct implementation. - struct __attribute__((randomize_layout)) s { + struct s { char *a; char *b; char *c; - }; + }__attribute__((randomize_layout)); // Indicates that this struct should NOT be randomized by Randstruct implementation. - struct __attribute__((no_randomize_layout)) s { + struct s { char *a; char *b; char *c; - }; + }__attribute__((no_randomize_layout)); // Emits compiler warning. Struct is NOT randomized by Randstruct implementation. - struct __attribute__((randomize_layout)) __attribute__((no_randomize_layout)) s { + struct s { char *a; char *b; char *c; - }; + }__attribute__((randomize_layout)) __attribute__((no_randomize_layout)); }]; } From d1d871c843719d45ce742e7c82f6e4d4d5dd98f7 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 23:05:28 -0800 Subject: [PATCH 44/87] added frandstruct-seed= to CC1Options.td --- clang/include/clang/Driver/CC1Options.td | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index cead87201eee74..6682b27bae16c0 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -422,6 +422,8 @@ def fcaret_diagnostics_max_lines : HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; +def frandstruct_seed_EQ : Separate<["-"], "frandstruct-seed">, MetaVarName<"">, + HelpText<"Randomization seed for random struct layouts">; def verify_EQ : CommaJoined<["-"], "verify=">, MetaVarName<"">, HelpText<"Verify diagnostic output using comment directives that start with" From efa2157fc16196be214c48dd3284c7d4e24e5e82 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 23:06:25 -0800 Subject: [PATCH 45/87] added frandstruct-seed= to CC1Options.td --- clang/include/clang/Driver/CC1Options.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 6682b27bae16c0..2314d483203b12 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -422,7 +422,7 @@ def fcaret_diagnostics_max_lines : HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; -def frandstruct_seed_EQ : Separate<["-"], "frandstruct-seed">, MetaVarName<"">, +def frandstruct_seed_EQ : Separate<["-"], "frandstruct-seed=">, MetaVarName<"">, HelpText<"Randomization seed for random struct layouts">; def verify_EQ : CommaJoined<["-"], "verify=">, MetaVarName<"">, From 7a329b5ea5a99da7397c99f9b60f6cde2db6c214 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 23:17:08 -0800 Subject: [PATCH 46/87] removing = --- clang/include/clang/Driver/CC1Options.td | 2 +- clang/lib/Driver/Job.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 2314d483203b12..9563607eccd11b 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -422,7 +422,7 @@ def fcaret_diagnostics_max_lines : HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; -def frandstruct_seed_EQ : Separate<["-"], "frandstruct-seed=">, MetaVarName<"">, +def frandstruct_seed : Separate<["-"], "frandstruct-seed">, MetaVarName<"">, HelpText<"Randomization seed for random struct layouts">; def verify_EQ : CommaJoined<["-"], "verify=">, MetaVarName<"">, diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index f3cf9ef76b1025..c8d3336f6dfce3 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -342,7 +342,8 @@ int Command::Execute(ArrayRef> Redirects, if (!RandstructSeed.empty()) { //Args.push_back("-frandstruct-seed=" + RandstructSeed); - Args.push_back("-frandstruct-seed=IAMASEED"); + Args.push_back("-frandstruct-seed"); + Args.push_back("IAMSEED"); } return llvm::sys::ExecuteAndWait( Executable, Args, Env, Redirects, /*secondsToWait*/ 0, From 495b157601348e70cf3d3a18df9b444b0e6ca9a2 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sat, 23 Feb 2019 23:59:27 -0800 Subject: [PATCH 47/87] removing = --- clang/lib/Frontend/CompilerInvocation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d2b7dbe5306ff9..213522dc08e698 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1670,7 +1670,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); } - if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed_EQ)) { + if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { llvm::errs() << "ParseFrontendArgs; " << RandstructSeed << "\n"; RandstructSeed = A->getValue(0); strcpy(cstr, A->getValue(0)); From 651fdc48cc3621be21c84de8ebc75a09bcfebd27 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sun, 24 Feb 2019 01:05:11 -0800 Subject: [PATCH 48/87] error: linker -f may not be used without -shared --- clang/lib/AST/RecordFieldReorganizer.cpp | 5 +---- clang/lib/Driver/Job.cpp | 12 ++++++------ clang/lib/Driver/ToolChains/Clang.cpp | 5 ----- clang/lib/Frontend/CompilerInvocation.cpp | 2 -- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index ce0de82764f62e..7d672843c87823 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -99,8 +99,6 @@ const size_t CACHE_LINE = 64; SmallVector Bucket::randomize() { // FIXME use seed llvm::errs() << "Bucket::randomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << " \n"; - llvm::errs() << "Bucket::randomize(); cstr" << std::string(cstr) << " at " << cstr << " : " << std::string(cstr).size() << " \n"; - //llvm::errs() << "I am Bucket::randomize() and RandomSeed is " << RandomSeed << "\n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); @@ -149,7 +147,6 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector randomize(SmallVector fields) { - llvm::errs() << "randomize(); " << RandstructSeed << " at " << &RandstructSeed << "\n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); @@ -240,7 +237,7 @@ SmallVector perfrandomize(const ASTContext &ctx, buckets.push_back(std::move(currentBitfieldRun)); } - llvm::errs() << "perfrandomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; + llvm::errs() << "perfrandomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(buckets), std::end(buckets), rng); diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index c8d3336f6dfce3..4f77d70da71756 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -335,16 +335,16 @@ int Command::Execute(ArrayRef> Redirects, if (ResponseFile == nullptr) { Argv.push_back(Executable); - Argv.append(Arguments.begin(), Arguments.end()); - Argv.push_back(nullptr); - - auto Args = llvm::toStringRefArray(Argv.data()); if (!RandstructSeed.empty()) { //Args.push_back("-frandstruct-seed=" + RandstructSeed); - Args.push_back("-frandstruct-seed"); - Args.push_back("IAMSEED"); + Argv.push_back("-frandstruct-seed"); + Argv.push_back( RandstructSeed ); } + Argv.append(Arguments.begin(), Arguments.end()); + Argv.push_back(nullptr); + + auto Args = llvm::toStringRefArray(Argv.data()); return llvm::sys::ExecuteAndWait( Executable, Args, Env, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a8bb840b598572..7637d1f6c56b64 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4412,13 +4412,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { //CmdArgs.push_back(A->getValue()); - llvm::errs() << "handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; RandstructSeed.assign(A->getValue(0)); - strcpy(cstr,A->getValue(0)); - llvm::errs() << "cstr: " << std::string(cstr) << "\n"; - llvm::errs() << "handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; } - llvm::errs() << "handling switch; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 213522dc08e698..49abb457eff404 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1671,9 +1671,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ActionName = A->getValue(); } if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { - llvm::errs() << "ParseFrontendArgs; " << RandstructSeed << "\n"; RandstructSeed = A->getValue(0); - strcpy(cstr, A->getValue(0)); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) From 013a77d9123ed4213f0be052d3c06a585c11ec56 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sun, 24 Feb 2019 01:08:46 -0800 Subject: [PATCH 49/87] error: linker -f may not be used without -shared --- clang/lib/Driver/Job.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 4f77d70da71756..07baebb235be16 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -339,7 +339,7 @@ int Command::Execute(ArrayRef> Redirects, { //Args.push_back("-frandstruct-seed=" + RandstructSeed); Argv.push_back("-frandstruct-seed"); - Argv.push_back( RandstructSeed ); + Argv.push_back( RandstructSeed.c_str() ); } Argv.append(Arguments.begin(), Arguments.end()); Argv.push_back(nullptr); From 184695db7726d39fccfcf60deba2eeea0438faba Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sun, 24 Feb 2019 01:51:18 -0800 Subject: [PATCH 50/87] error: linker -f may not be used without -shared --- clang/lib/Driver/Job.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 07baebb235be16..b8e52267d18f00 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -335,13 +335,12 @@ int Command::Execute(ArrayRef> Redirects, if (ResponseFile == nullptr) { Argv.push_back(Executable); + Argv.append(Arguments.begin(), Arguments.end()); if (!RandstructSeed.empty()) { //Args.push_back("-frandstruct-seed=" + RandstructSeed); - Argv.push_back("-frandstruct-seed"); - Argv.push_back( RandstructSeed.c_str() ); + Argv.push_back( ("-frandstruct-seed=" + RandstructSeed).c_str() ); } - Argv.append(Arguments.begin(), Arguments.end()); Argv.push_back(nullptr); auto Args = llvm::toStringRefArray(Argv.data()); From 0594d7e431a3481360105b92ca96c1aa31ce50ec Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sun, 24 Feb 2019 02:58:47 -0800 Subject: [PATCH 51/87] gen. commit --- clang/lib/Driver/Job.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index b8e52267d18f00..cd380c6d549e34 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -339,7 +339,8 @@ int Command::Execute(ArrayRef> Redirects, if (!RandstructSeed.empty()) { //Args.push_back("-frandstruct-seed=" + RandstructSeed); - Argv.push_back( ("-frandstruct-seed=" + RandstructSeed).c_str() ); + Argv.push_back( "-frandstruct-seed" ); + Argv.push_back( RandstructSeed.c_str() ); } Argv.push_back(nullptr); From 3656e0178566f7795a0299d9fbc290fb869314df Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sun, 24 Feb 2019 12:33:37 -0800 Subject: [PATCH 52/87] wip fixing linker errors --- clang/lib/Frontend/CompilerInvocation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 49abb457eff404..506163b28caf0a 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1672,6 +1672,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, } if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { RandstructSeed = A->getValue(0); + Args.eraseArg(OPT_frandstruct_seed); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) From f07aff2b30d392c9dfe48545109b94305dfcb910 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Sun, 24 Feb 2019 13:30:03 -0800 Subject: [PATCH 53/87] wip fixing linker errors --- clang/lib/Frontend/CompilerInvocation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 506163b28caf0a..68607f99a295ff 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1673,6 +1673,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { RandstructSeed = A->getValue(0); Args.eraseArg(OPT_frandstruct_seed); + Args.print(llvm::errs()); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) From 213041f4ab999bfe81054a72724300a172a70f5e Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 02:16:22 -0800 Subject: [PATCH 54/87] wip fixing linker errors --- clang/lib/Driver/Job.cpp | 7 ++++--- clang/lib/Driver/ToolChains/Clang.cpp | 4 +++- clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 1 - gdbcommands | 8 -------- notes | 12 ------------ 5 files changed, 7 insertions(+), 25 deletions(-) delete mode 100644 gdbcommands delete mode 100644 notes diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index cd380c6d549e34..7161e36d64713a 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -336,11 +336,12 @@ int Command::Execute(ArrayRef> Redirects, if (ResponseFile == nullptr) { Argv.push_back(Executable); Argv.append(Arguments.begin(), Arguments.end()); - if (!RandstructSeed.empty()) + // If this is the clang tool, and seed is empty, push argument back + // FIXME: figure out where Arguments are set, and put this there + if ( ("clang" == (*this).getCreator().getName() ) && !RandstructSeed.empty()) { //Args.push_back("-frandstruct-seed=" + RandstructSeed); - Argv.push_back( "-frandstruct-seed" ); - Argv.push_back( RandstructSeed.c_str() ); + Argv.push_back( ("-frandstruct-seed=" + RandstructSeed).c_str() ); } Argv.push_back(nullptr); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7637d1f6c56b64..b87e1631ac4490 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4411,7 +4411,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { - //CmdArgs.push_back(A->getValue()); + CmdArgs.push_back("-frandstruct"); + CmdArgs.push_back(A->getValue(0)); RandstructSeed.assign(A->getValue(0)); } @@ -5375,6 +5376,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } else { + // this is where first job is added C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 4abd98f60bf28a..c226838786f092 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -268,7 +268,6 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { std::unique_ptr Act(CreateFrontendAction(*Clang)); if (!Act) return false; - //llvm::errs() << "cstr: " << std::string(clang::cstr) << "\n"; bool Success = Clang->ExecuteAction(*Act); if (Clang->getFrontendOpts().DisableFree) llvm::BuryPointer(std::move(Act)); diff --git a/gdbcommands b/gdbcommands deleted file mode 100644 index 78f5f209fcd002..00000000000000 --- a/gdbcommands +++ /dev/null @@ -1,8 +0,0 @@ -set follow-fork-mode child -set print pretty on -break RandFieldReorganizer.cpp:103 -break RandFieldReorganizer.cpp:152 -break RandFieldReorganizer.cpp:159 -break CompilerInvocation.cpp:1673 -break Clang.cpp:4413 -break RecordLayoutBuild.cpp:2993 diff --git a/notes b/notes deleted file mode 100644 index f9b9b914c5b805..00000000000000 --- a/notes +++ /dev/null @@ -1,12 +0,0 @@ -Program.cpp:37 is the first location that doesn't see cstr -CompilerInvocation.cpp:1679 is next relevant location - -gdb: set logging on -gdb: set logging file filename - -Program.cpp:37 Execute() takes Args - where are they defined? - -Job.cpp:341 - auto Args = llvm::toStringRefArray(Argv.data()); - -class Command.Arguments From ab0393f272b149454fe9ac3b5ef764664d0e78a2 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 03:12:04 -0800 Subject: [PATCH 55/87] wip fixing linker errors --- clang/lib/Driver/Job.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 7161e36d64713a..e363ea8d250037 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -336,13 +336,16 @@ int Command::Execute(ArrayRef> Redirects, if (ResponseFile == nullptr) { Argv.push_back(Executable); Argv.append(Arguments.begin(), Arguments.end()); + // If this is the clang tool, and seed is empty, push argument back // FIXME: figure out where Arguments are set, and put this there +#if 0 if ( ("clang" == (*this).getCreator().getName() ) && !RandstructSeed.empty()) { //Args.push_back("-frandstruct-seed=" + RandstructSeed); Argv.push_back( ("-frandstruct-seed=" + RandstructSeed).c_str() ); } +#endif Argv.push_back(nullptr); auto Args = llvm::toStringRefArray(Argv.data()); From d923c6f47bad0f28dca1e53f9ef8283708783cf9 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 05:11:23 -0800 Subject: [PATCH 56/87] wip fixing linker errors --- clang/lib/Driver/ToolChains/Clang.cpp | 4 +-- stacktraces | 48 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 stacktraces diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b87e1631ac4490..ae9711cba42acd 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4411,8 +4411,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { - CmdArgs.push_back("-frandstruct"); - CmdArgs.push_back(A->getValue(0)); + CmdArgs.push_back("-frandstruct=" + A->getValue(0)); + //CmdArgs.push_back(A->getValue(0)); RandstructSeed.assign(A->getValue(0)); } diff --git a/stacktraces b/stacktraces new file mode 100644 index 00000000000000..f5c416712c242b --- /dev/null +++ b/stacktraces @@ -0,0 +1,48 @@ +################ +ConstructJob +#0 clang::driver::Command::Command (this=0xbcaf570, Source=..., Creator=..., + Executable=0xbcae440 "/home/cantrel2/projects/llvm-project/seedarg/build/bin/clang", Arguments=..., Inputs=...) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Job.cpp:44 +#1 0x000000000443cc68 in llvm::make_unique&, llvm::SmallVector const&> (args=..., args=..., args=..., args=..., args=...) + at /home/cantrel2/projects/llvm-project/seedarg/llvm/include/llvm/ADT/STLExtras.h:1349 +#2 0x000000000442b7e8 in clang::driver::tools::Clang::ConstructJob ( + this=0xbcd8780, C=..., JA=..., Output=..., Inputs=..., Args=..., + LinkingOutput=0x0) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/ToolChains/Clang.cpp:5380 +#3 0x00000000043d022e in clang::driver::Driver::BuildJobsForActionNoCache ( + this=0x7fffffffc648, C=..., A=0xbcd8530, TC=0xbcacce0, BoundArch=..., + AtTopLevel=false, MultipleArchs=false, LinkingOutput=0x0, + CachedResults=std::map with 1 element = {...}, + TargetDeviceOffloadKind=clang::driver::Action::OFK_None) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:4160 +#4 0x00000000043ce7af in clang::driver::Driver::BuildJobsForAction ( +---Type to continue, or q to quit--- + this=0x7fffffffc648, C=..., A=0xbcd8530, TC=0xbcacce0, BoundArch=..., + AtTopLevel=false, MultipleArchs=false, LinkingOutput=0x0, + CachedResults=std::map with 1 element = {...}, + TargetDeviceOffloadKind=clang::driver::Action::OFK_None) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:3897 +#5 0x00000000043cf304 in clang::driver::Driver::BuildJobsForActionNoCache ( + this=0x7fffffffc648, C=..., A=0xbcd8590, TC=0xbcacce0, BoundArch=..., + AtTopLevel=true, MultipleArchs=false, LinkingOutput=0x0, + CachedResults=std::map with 1 element = {...}, + TargetDeviceOffloadKind=clang::driver::Action::OFK_None) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:4035 +#6 0x00000000043ce7af in clang::driver::Driver::BuildJobsForAction ( + this=0x7fffffffc648, C=..., A=0xbcd8590, TC=0xbcacce0, BoundArch=..., + AtTopLevel=true, MultipleArchs=false, LinkingOutput=0x0, + CachedResults=std::map with 1 element = {...}, + TargetDeviceOffloadKind=clang::driver::Action::OFK_None) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:3897 +#7 0x00000000043c84be in clang::driver::Driver::BuildJobs ( + this=0x7fffffffc648, C=...) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:---Type to continue, or q to quit--- +3509 +#8 0x00000000043c43a8 in clang::driver::Driver::BuildCompilation ( + this=0x7fffffffc648, ArgList=...) + at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:1119 +#9 0x0000000001296ecd in main (argc_=3, argv_=0x7fffffffdd48) + at /home/cantrel2/projects/llvm-project/seedarg/clang/tools/driver/driver.cpp:457 + + +####################### From 25246d26887347fd7e391dffa28bc90c1a840e1a Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 05:40:15 -0800 Subject: [PATCH 57/87] wip fixing linker errors --- clang/lib/Driver/ToolChains/Clang.cpp | 3 ++- clang/lib/Frontend/FrontendAction.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index ae9711cba42acd..9308e147bec174 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4411,8 +4411,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { - CmdArgs.push_back("-frandstruct=" + A->getValue(0)); + CmdArgs.push_back( ("-frandstruct=" + std::string(A->getValue(0))).c_str() ); //CmdArgs.push_back(A->getValue(0)); + //CmdArgs.push_back( A-> RandstructSeed.assign(A->getValue(0)); } diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 7de6427eb88548..3392923380f33c 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -931,7 +931,6 @@ bool FrontendAction::Execute() { llvm::TimeRegion Timer(CI.getFrontendTimer()); ExecuteAction(); } - //llvm::errs() << "FrontendAction::Execute(); " << std::string(cstr) << "\n"; else ExecuteAction(); // If we are supposed to rebuild the global module index, do so now unless From 14557040512090d26333cca6847f7bb810cabe09 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 05:57:49 -0800 Subject: [PATCH 58/87] wip fixing linker errors --- clang/lib/AST/RecordLayoutBuilder.cpp | 2 - clang/lib/CodeGen/CodeGenAction.cpp | 1 - clang/lib/Driver/ToolChains/Clang.cpp | 5 +-- clang/lib/Frontend/CompilerInvocation.cpp | 1 + stacktraces | 48 ----------------------- 5 files changed, 2 insertions(+), 55 deletions(-) delete mode 100644 stacktraces diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index a20d8a2f73a4ff..4cb5511d781975 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -22,8 +22,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" -//std::string RandstructSeed = "myrandomseed"; - using namespace clang; namespace { diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index c034268fb78136..0b631f72e6e4a4 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -1043,7 +1043,6 @@ void CodeGenAction::ExecuteAction() { return; } - //llvm::errs() << "CodeGenAction::ExecuteAction(); " << std::string(cstr) << "\n"; // Otherwise follow the normal AST path. this->ASTFrontendAction::ExecuteAction(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 9308e147bec174..dfd19c035c283f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -46,14 +46,11 @@ #include // For getuid(). #endif -//std::string RandstructSeed = "initialseedstring"; - using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; - static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC)) { @@ -4409,7 +4406,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine(N))); } - // -frandstruct-seed + // -frandstruct-seed parent process if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { CmdArgs.push_back( ("-frandstruct=" + std::string(A->getValue(0))).c_str() ); //CmdArgs.push_back(A->getValue(0)); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 68607f99a295ff..6de73abef9b05c 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1670,6 +1670,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); } + // child process handle arguments if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { RandstructSeed = A->getValue(0); Args.eraseArg(OPT_frandstruct_seed); diff --git a/stacktraces b/stacktraces deleted file mode 100644 index f5c416712c242b..00000000000000 --- a/stacktraces +++ /dev/null @@ -1,48 +0,0 @@ -################ -ConstructJob -#0 clang::driver::Command::Command (this=0xbcaf570, Source=..., Creator=..., - Executable=0xbcae440 "/home/cantrel2/projects/llvm-project/seedarg/build/bin/clang", Arguments=..., Inputs=...) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Job.cpp:44 -#1 0x000000000443cc68 in llvm::make_unique&, llvm::SmallVector const&> (args=..., args=..., args=..., args=..., args=...) - at /home/cantrel2/projects/llvm-project/seedarg/llvm/include/llvm/ADT/STLExtras.h:1349 -#2 0x000000000442b7e8 in clang::driver::tools::Clang::ConstructJob ( - this=0xbcd8780, C=..., JA=..., Output=..., Inputs=..., Args=..., - LinkingOutput=0x0) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/ToolChains/Clang.cpp:5380 -#3 0x00000000043d022e in clang::driver::Driver::BuildJobsForActionNoCache ( - this=0x7fffffffc648, C=..., A=0xbcd8530, TC=0xbcacce0, BoundArch=..., - AtTopLevel=false, MultipleArchs=false, LinkingOutput=0x0, - CachedResults=std::map with 1 element = {...}, - TargetDeviceOffloadKind=clang::driver::Action::OFK_None) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:4160 -#4 0x00000000043ce7af in clang::driver::Driver::BuildJobsForAction ( ----Type to continue, or q to quit--- - this=0x7fffffffc648, C=..., A=0xbcd8530, TC=0xbcacce0, BoundArch=..., - AtTopLevel=false, MultipleArchs=false, LinkingOutput=0x0, - CachedResults=std::map with 1 element = {...}, - TargetDeviceOffloadKind=clang::driver::Action::OFK_None) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:3897 -#5 0x00000000043cf304 in clang::driver::Driver::BuildJobsForActionNoCache ( - this=0x7fffffffc648, C=..., A=0xbcd8590, TC=0xbcacce0, BoundArch=..., - AtTopLevel=true, MultipleArchs=false, LinkingOutput=0x0, - CachedResults=std::map with 1 element = {...}, - TargetDeviceOffloadKind=clang::driver::Action::OFK_None) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:4035 -#6 0x00000000043ce7af in clang::driver::Driver::BuildJobsForAction ( - this=0x7fffffffc648, C=..., A=0xbcd8590, TC=0xbcacce0, BoundArch=..., - AtTopLevel=true, MultipleArchs=false, LinkingOutput=0x0, - CachedResults=std::map with 1 element = {...}, - TargetDeviceOffloadKind=clang::driver::Action::OFK_None) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:3897 -#7 0x00000000043c84be in clang::driver::Driver::BuildJobs ( - this=0x7fffffffc648, C=...) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:---Type to continue, or q to quit--- -3509 -#8 0x00000000043c43a8 in clang::driver::Driver::BuildCompilation ( - this=0x7fffffffc648, ArgList=...) - at /home/cantrel2/projects/llvm-project/seedarg/clang/lib/Driver/Driver.cpp:1119 -#9 0x0000000001296ecd in main (argc_=3, argv_=0x7fffffffdd48) - at /home/cantrel2/projects/llvm-project/seedarg/clang/tools/driver/driver.cpp:457 - - -####################### From 3dcf7485f80353b8423fbb95deeafcd9b9bb4fef Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 07:52:27 -0800 Subject: [PATCH 59/87] wip fixing linker errors --- clang/lib/Driver/ToolChains/Clang.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index dfd19c035c283f..0b39bc76dc554d 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4408,9 +4408,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed parent process if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { - CmdArgs.push_back( ("-frandstruct=" + std::string(A->getValue(0))).c_str() ); - //CmdArgs.push_back(A->getValue(0)); - //CmdArgs.push_back( A-> + //CmdArgs.push_back( ("-frandstruct=" + std::string(A->getValue(0))).c_str() ); + //CmdArgs.push_back( (A->getSpelling() + std::string(A->getValue(0))) ); + CmdArgs.push_back( "-frandstruct" ); + CmdArgs.push_back(A->getValue(0)); RandstructSeed.assign(A->getValue(0)); } From 46b491ebf6778dd85f2f1cdfb11ee0e2f2cb8d39 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 13:12:22 -0800 Subject: [PATCH 60/87] generic commit --- clang/lib/Driver/ToolChains/Clang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 0b39bc76dc554d..7c540d336abfc9 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4410,7 +4410,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { //CmdArgs.push_back( ("-frandstruct=" + std::string(A->getValue(0))).c_str() ); //CmdArgs.push_back( (A->getSpelling() + std::string(A->getValue(0))) ); - CmdArgs.push_back( "-frandstruct" ); + CmdArgs.push_back( "-frandstruct-seed" ); CmdArgs.push_back(A->getValue(0)); RandstructSeed.assign(A->getValue(0)); } From d1498239364522ba83dfaa6b5c7336fb817cd10d Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 15:10:03 -0800 Subject: [PATCH 61/87] generic commit --- clang/include/clang/AST/RandstructSeed.h | 1 - clang/lib/AST/RecordFieldReorganizer.cpp | 3 +-- clang/lib/Driver/Job.cpp | 10 ---------- clang/lib/Driver/ToolChains/Clang.cpp | 3 +-- clang/lib/Frontend/CompilerInvocation.cpp | 3 +-- 5 files changed, 3 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/AST/RandstructSeed.h b/clang/include/clang/AST/RandstructSeed.h index 7257558ad7bbdd..483dda27b14e57 100644 --- a/clang/include/clang/AST/RandstructSeed.h +++ b/clang/include/clang/AST/RandstructSeed.h @@ -3,6 +3,5 @@ #include namespace clang { extern std::string RandstructSeed; -extern char cstr[128]; } #endif diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 7d672843c87823..ed3f1d8ac1720d 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -24,8 +24,6 @@ // FIXME: Find a better alternative to SmallVector with hardcoded size! namespace clang { -std::string RandstructSeed = "someseed"; -char cstr[128]; void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, const RecordDecl *D) const { @@ -147,6 +145,7 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector randomize(SmallVector fields) { + llvm::errs() << "randomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << " \n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index e363ea8d250037..27c74247a0fa9f 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -13,7 +13,6 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" -#include "clang/AST/RandstructSeed.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -337,15 +336,6 @@ int Command::Execute(ArrayRef> Redirects, Argv.push_back(Executable); Argv.append(Arguments.begin(), Arguments.end()); - // If this is the clang tool, and seed is empty, push argument back - // FIXME: figure out where Arguments are set, and put this there -#if 0 - if ( ("clang" == (*this).getCreator().getName() ) && !RandstructSeed.empty()) - { - //Args.push_back("-frandstruct-seed=" + RandstructSeed); - Argv.push_back( ("-frandstruct-seed=" + RandstructSeed).c_str() ); - } -#endif Argv.push_back(nullptr); auto Args = llvm::toStringRefArray(Argv.data()); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7c540d336abfc9..0e327c4fa72958 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4412,7 +4412,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, //CmdArgs.push_back( (A->getSpelling() + std::string(A->getValue(0))) ); CmdArgs.push_back( "-frandstruct-seed" ); CmdArgs.push_back(A->getValue(0)); - RandstructSeed.assign(A->getValue(0)); + //RandstructSeed.assign(A->getValue(0)); } // -fvisibility= and -fvisibility-ms-compat are of a piece. @@ -5375,7 +5375,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } else { - // this is where first job is added C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 6de73abef9b05c..d51930c32b6c42 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1673,8 +1673,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, // child process handle arguments if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { RandstructSeed = A->getValue(0); - Args.eraseArg(OPT_frandstruct_seed); - Args.print(llvm::errs()); + //Args.eraseArg(OPT_frandstruct_seed); do we need to erase it? } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) From 58cfc9be6185486949bcf4c1cc539c7a4787ba41 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 15:28:18 -0800 Subject: [PATCH 62/87] generic commit --- clang/lib/Driver/Job.cpp | 1 - clang/lib/Driver/ToolChains/Clang.cpp | 4 ---- clang/lib/Frontend/CompilerInvocation.cpp | 2 -- 3 files changed, 7 deletions(-) diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 27c74247a0fa9f..1af454f8889cd7 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -335,7 +335,6 @@ int Command::Execute(ArrayRef> Redirects, if (ResponseFile == nullptr) { Argv.push_back(Executable); Argv.append(Arguments.begin(), Arguments.end()); - Argv.push_back(nullptr); auto Args = llvm::toStringRefArray(Argv.data()); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 0e327c4fa72958..920399c44b1374 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/RandstructSeed.h" #include "Clang.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" @@ -4408,11 +4407,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frandstruct-seed parent process if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { - //CmdArgs.push_back( ("-frandstruct=" + std::string(A->getValue(0))).c_str() ); - //CmdArgs.push_back( (A->getSpelling() + std::string(A->getValue(0))) ); CmdArgs.push_back( "-frandstruct-seed" ); CmdArgs.push_back(A->getValue(0)); - //RandstructSeed.assign(A->getValue(0)); } // -fvisibility= and -fvisibility-ms-compat are of a piece. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d51930c32b6c42..4066b70396d7d3 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/RandstructSeed.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" @@ -1673,7 +1672,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, // child process handle arguments if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { RandstructSeed = A->getValue(0); - //Args.eraseArg(OPT_frandstruct_seed); do we need to erase it? } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) From e0dcc7a606ddc6c38b0ea99889151e3114c36b93 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 15:33:50 -0800 Subject: [PATCH 63/87] generic commit --- clang/lib/Frontend/CompilerInvocation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 4066b70396d7d3..3c3cb656fe300d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/Randstruct.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" From 8590e8e4e93703b329d5266dbda004ee669afd2a Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 15:38:37 -0800 Subject: [PATCH 64/87] generic commit --- clang/lib/Frontend/CompilerInvocation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 3c3cb656fe300d..249b5d4c690db4 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Randstruct.h" +#include "clang/AST/RandstructSeed.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" From 690b679c62fab91f42a5d8dea3fdea4af5e8e0c2 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 15:45:05 -0800 Subject: [PATCH 65/87] generic commit --- clang/lib/AST/RecordFieldReorganizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index ed3f1d8ac1720d..27820be09bb3ac 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -24,6 +24,7 @@ // FIXME: Find a better alternative to SmallVector with hardcoded size! namespace clang { +std::string RandstructSeed = ""; void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, const RecordDecl *D) const { From 82bd310ac4b01937bab78418488a980f945cd975 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 18:45:41 -0800 Subject: [PATCH 66/87] generic commit --- clang/lib/AST/RecordFieldReorganizer.cpp | 3 --- clang/lib/AST/RecordLayoutBuilder.cpp | 1 - 2 files changed, 4 deletions(-) diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 27820be09bb3ac..52bda0dabff8b9 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -97,7 +97,6 @@ const size_t CACHE_LINE = 64; SmallVector Bucket::randomize() { // FIXME use seed - llvm::errs() << "Bucket::randomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << " \n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); @@ -146,7 +145,6 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector randomize(SmallVector fields) { - llvm::errs() << "randomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << " \n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); @@ -237,7 +235,6 @@ SmallVector perfrandomize(const ASTContext &ctx, buckets.push_back(std::move(currentBitfieldRun)); } - llvm::errs() << "perfrandomize(); " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(buckets), std::end(buckets), rng); diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 4cb5511d781975..65b83e572992de 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2990,7 +2990,6 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { - llvm::errs() << "ShouldBeRandomized; " << RandstructSeed << " at " << &RandstructSeed << " : " << RandstructSeed.size() << "\n"; Randstruct randstruct; randstruct.reorganizeFields(*this, D); } From 99497983cdf4a1feb4494a05b7134c7d8fa213a8 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 25 Feb 2019 19:05:16 -0800 Subject: [PATCH 67/87] Docs for the single attribute, 'randomize_layout'. --- clang/include/clang/Basic/Attr.td | 9 +------- clang/include/clang/Basic/AttrDocs.td | 33 +++------------------------ clang/lib/AST/RecordLayoutBuilder.cpp | 6 +---- 3 files changed, 5 insertions(+), 43 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 4cde6982dbadd4..8099366d19a0b4 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3206,12 +3206,5 @@ def RandomizeLayout : InheritableAttr { let Spellings = [GCC<"randomize_layout">, Declspec<"randomize_layout">, Keyword<"randomize_layout">]; let Subjects = SubjectList<[Record]>; - let Documentation = [Undocumented]; -} - -def NoRandomizeLayout : InheritableAttr { - let Spellings = [GCC<"no_randomize_layout">, Declspec<"no_randomize_layout">, - Keyword<"no_randomize_layout">]; - let Subjects = SubjectList<[Record]>; - let Documentation = [Undocumented]; + let Documentation = [ClangRandstructDocs]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 24a48ed68c2398..d5832a7503bfe7 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4099,24 +4099,11 @@ When compiled without ``-fobjc-arc``, this attribute is ignored. def ClangRandstructDocs : Documentation { let Category = DocCatVariable; - let Heading = "randomize_layout, no_randomize_layout"; + let Heading = "randomize_layout; let Content = [{ -The attributes ``randomize_layout`` and ``no_randomize_layout`` can be applied -to a record. - -``randomize_layout`` instructs the compiler to randomize the memory layout +The attribute ``randomize_layout`` can be applied to the declaration of +a record. ``randomize_layout`` instructs the compiler to randomize the memory layout of the member variables of the record. - -Conversely, ``no_randomize_layout`` is used to indicate that if using the -automatic strucuture selection feature of the Randstruct implementation, the -compiler should not shuffle the members of the record. - -In the event that a record is labeled with both attributes, the compiler will -emit a warning indicating that these two cannot be used on the same record. -The default behavior in this case is to not randomize the struct, as the -attribute ``no_randomize_layout`` takes precedence over ``randomize_layout``. -This is implementation defined behavior. - .. code-block:: c // Indicates that this struct should be randomized by Randstruct implementation. @@ -4125,19 +4112,5 @@ This is implementation defined behavior. char *b; char *c; }__attribute__((randomize_layout)); - - // Indicates that this struct should NOT be randomized by Randstruct implementation. - struct s { - char *a; - char *b; - char *c; - }__attribute__((no_randomize_layout)); - - // Emits compiler warning. Struct is NOT randomized by Randstruct implementation. - struct s { - char *a; - char *b; - char *c; - }__attribute__((randomize_layout)) __attribute__((no_randomize_layout)); }]; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index cff5578c6a2cf1..cf0c229bc4f61f 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2988,12 +2988,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; bool ShouldBeRandomized = D->getAttr() != nullptr; - bool NotToBeRandomized = D->getAttr() != nullptr; - if (ShouldBeRandomized && NotToBeRandomized) { - getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_conflict); - } - else if (ShouldBeRandomized) { + if (ShouldBeRandomized) { Randstruct randstruct; randstruct.reorganizeFields(*this,D); } From f06d4cc861b166735a8b1e57faf287e4e7ea7c11 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 25 Feb 2019 19:16:08 -0800 Subject: [PATCH 68/87] touched up other docs ad ran 'clang-format' --- clang/include/clang/Basic/DiagnosticASTKinds.td | 6 ------ clang/lib/Sema/SemaDeclAttr.cpp | 3 --- .../Misc/pragma-attribute-supported-attributes-list.test | 1 - 3 files changed, 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 412f3fd69bbbf2..c2a390fa465d81 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -343,10 +343,4 @@ def warn_padded_struct_size : Warning< InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; - -// RandStruct implementation -def warn_randomize_attr_conflict : Warning< - "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes; " - "attribute 'no_randomize_layout' takes precedence">, InGroup>; - } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 60aa1fa3457e57..d1f0513da1219f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6856,9 +6856,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_RandomizeLayout: handleSimpleAttribute(S, D, AL); break; - case ParsedAttr::AT_NoRandomizeLayout: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 828aad4a874ea5..45012ae9bfdd11 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -80,7 +80,6 @@ // CHECK-NEXT: NoInstrumentFunction (SubjectMatchRule_function) // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function) // CHECK-NEXT: NoMips16 (SubjectMatchRule_function) -// CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) From 6fedc9d410abe42998bc1e9a29ded0cd8663be11 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 26 Feb 2019 03:48:56 +0000 Subject: [PATCH 69/87] Refactored the auto selection code --- .../clang/AST/RecordFieldReorganizer.h | 2 ++ clang/lib/AST/RecordFieldReorganizer.cpp | 26 +++++-------------- clang/lib/AST/RecordLayoutBuilder.cpp | 9 +++---- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 7f15e1b3b10ed5..494cfa9433c024 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -38,6 +38,8 @@ class RecordFieldReorganizer { }; class Randstruct : public RecordFieldReorganizer { +public: + bool isTriviallyRandomizable(const RecordDecl *D) const; protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 0190acd50c922f..f02f0fe849c6ce 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -35,11 +35,6 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, mutateGuard.insert(f); fields.push_back(f); } - if(D->getAttr() == nullptr){ - if(!autostructselect(fields)){ - return; - } - } // Now allow subclass implementations to reorder the fields reorganize(C, D, fields); @@ -54,20 +49,6 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, commit(D, fields); } -bool RecordFieldReorganizer::autostructselect(const SmallVector fields) const { - - bool Select = true; - for (auto f : fields){ - auto t = f->getFunctionType(); - auto s = ((FieldDecl *)f)->getNameAsString(); - llvm::errs() << "Function " << s << " type: " << t << "\n"; - if(t == nullptr){ - Select = false; - break; - } - } - return Select; -} void RecordFieldReorganizer::commit( const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const { Decl *First, *Last; @@ -266,5 +247,10 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, SmallVector randomized = perfrandomize(C, NewOrder); NewOrder = randomized; } - +bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) const { + for (auto f : D->fields()){ + if(f->getFunctionType() == nullptr){ return false; } + } + return true; +} } // namespace clang diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 8f8b3671214b36..749659dbc065dc 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2986,11 +2986,10 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (Entry) return *Entry; const ASTRecordLayout *NewEntry = nullptr; - - bool ShouldBeRandomized = D->getAttr() != nullptr; - if (true) { - Randstruct randstruct; - randstruct.reorganizeFields(*this, D); + Randstruct randstruct; + bool ShouldBeRandomized = randstruct.isTriviallyRandomizable(D) || D->getAttr() != nullptr; + if(ShouldBeRandomized){ + randstruct.reorganizeFields(*this, D); } if (isMsLayout(*this)) { From 6900a6263a77596594eef7514749524e2d68cf7a Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Mon, 25 Feb 2019 19:49:00 -0800 Subject: [PATCH 70/87] generic commit --- clang/include/clang/AST/RecordFieldReorganizer.h | 8 ++++++++ clang/lib/AST/RecordFieldReorganizer.cpp | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 1f2562b5e389cd..7f52c635a1b27a 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -37,7 +37,15 @@ class RecordFieldReorganizer { }; class Randstruct : public RecordFieldReorganizer { +public: + Randstruct(std::string seed) : Seq(seed.begin(), seed.end()), rng(Seq) {} +private: + std::seed_seq Seq; + std::default_random_engine rng; protected: + virtual SmallVector randomize() override; + SmallVector Randstruct::perfrandomize(const ASTContext &ctx, + SmallVector fields); virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; }; diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 52bda0dabff8b9..5ad21e643cf1ef 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -144,14 +144,16 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } -SmallVector randomize(SmallVector fields) { +SmallVector Randstruct::randomize(SmallVector fields) { std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } -SmallVector perfrandomize(const ASTContext &ctx, +Randstruct::Randstruct(std::String Seed) { RandstructSeed = Seed; } + +SmallVector Randstruct::perfrandomize(const ASTContext &ctx, SmallVector fields) { // All of the buckets produced by best-effort cache-line algorithm. std::vector> buckets; From 9cab894d94b0b2056a7908279d59e9729b60df76 Mon Sep 17 00:00:00 2001 From: tim-pugh Date: Tue, 26 Feb 2019 04:14:09 +0000 Subject: [PATCH 71/87] Changed frandstruct to randstruct --- clang/include/clang/Driver/CC1Options.td | 2 +- clang/include/clang/Driver/Options.td | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 6 +++--- clang/lib/Frontend/CompilerInvocation.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 9563607eccd11b..924122df92d60c 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -422,7 +422,7 @@ def fcaret_diagnostics_max_lines : HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; -def frandstruct_seed : Separate<["-"], "frandstruct-seed">, MetaVarName<"">, +def randstruct_seed : Separate<["-"], "randstruct-seed">, MetaVarName<"">, HelpText<"Randomization seed for random struct layouts">; def verify_EQ : CommaJoined<["-"], "verify=">, MetaVarName<"">, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index cb7efbf3edd474..b86c776e829e41 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1258,7 +1258,7 @@ def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">; def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group; -def frandstruct_seed_EQ : Joined<["-"], "frandstruct-seed=">, Group; +def randstruct_seed_EQ : Joined<["-"], "randstruct-seed=">, Group; def fms_extensions : Flag<["-"], "fms-extensions">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group, Flags<[CC1Option, CoreOption]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 920399c44b1374..ea62b795707044 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4405,9 +4405,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine(N))); } - // -frandstruct-seed parent process - if (Arg *A = Args.getLastArg(options::OPT_frandstruct_seed_EQ)) { - CmdArgs.push_back( "-frandstruct-seed" ); + // -randstruct-seed parent process + if (Arg *A = Args.getLastArg(options::OPT_randstruct_seed_EQ)) { + CmdArgs.push_back( "-randstruct-seed" ); CmdArgs.push_back(A->getValue(0)); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 249b5d4c690db4..cd08ac5847b3b7 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1671,7 +1671,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ActionName = A->getValue(); } // child process handle arguments - if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { + if (const Arg* A = Args.getLastArg(OPT_randstruct_seed)) { RandstructSeed = A->getValue(0); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); From ca2372fed0938854900437f1d9a1bc4c3bac53f9 Mon Sep 17 00:00:00 2001 From: Nixoncole Date: Mon, 25 Feb 2019 20:36:15 -0800 Subject: [PATCH 72/87] Removed 'header' that is only for when you include docs for multiple attributes --- clang/include/clang/Basic/AttrDocs.td | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index d5832a7503bfe7..a6f109f41d6da6 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4099,7 +4099,6 @@ When compiled without ``-fobjc-arc``, this attribute is ignored. def ClangRandstructDocs : Documentation { let Category = DocCatVariable; - let Heading = "randomize_layout; let Content = [{ The attribute ``randomize_layout`` can be applied to the declaration of a record. ``randomize_layout`` instructs the compiler to randomize the memory layout From 63cf353e1361f3cc5b46eb99125509311ef06879 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 26 Feb 2019 04:38:33 +0000 Subject: [PATCH 73/87] Added comments --- clang/include/clang/AST/RecordFieldReorganizer.h | 1 + clang/lib/AST/RecordFieldReorganizer.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 494cfa9433c024..48d0b24a8989ac 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -39,6 +39,7 @@ class RecordFieldReorganizer { class Randstruct : public RecordFieldReorganizer { public: + //Automatic Structure selection bool isTriviallyRandomizable(const RecordDecl *D) const; protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index f02f0fe849c6ce..88f8c2478e9567 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -248,7 +248,10 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, NewOrder = randomized; } bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) const { + for (auto f : D->fields()){ + //If an element of the structure does not have a + //function type is not a function pointer if(f->getFunctionType() == nullptr){ return false; } } return true; From 312a0e6f7f3296960af571271a7f78f969dcd167 Mon Sep 17 00:00:00 2001 From: tim-pugh Date: Tue, 26 Feb 2019 06:31:10 +0000 Subject: [PATCH 74/87] Revert "(#20) Merge RandomizeLayout regression test" This reverts commit b47a59e7aa050735fb089d8c3319dc95f856bb6c, reversing changes made to 753b226189a0ffd66cd0f785d16fe1110b35fda4. --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 8915de50f668dc..45012ae9bfdd11 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -117,7 +117,6 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) From 32fae7229429088be56746591b4d7f58e7f72a90 Mon Sep 17 00:00:00 2001 From: tim-pugh Date: Tue, 26 Feb 2019 07:24:01 +0000 Subject: [PATCH 75/87] Re-adding regression test fix --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 45012ae9bfdd11..8915de50f668dc 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -117,6 +117,7 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) From d95e6247f5ddd2812f03bd3a829d9299b751abfe Mon Sep 17 00:00:00 2001 From: tim-pugh Date: Tue, 26 Feb 2019 07:30:02 +0000 Subject: [PATCH 76/87] Revert "generic commit" This reverts commit 6900a6263a77596594eef7514749524e2d68cf7a. --- clang/include/clang/AST/RecordFieldReorganizer.h | 8 -------- clang/lib/AST/RecordFieldReorganizer.cpp | 6 ++---- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 7f52c635a1b27a..1f2562b5e389cd 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -37,15 +37,7 @@ class RecordFieldReorganizer { }; class Randstruct : public RecordFieldReorganizer { -public: - Randstruct(std::string seed) : Seq(seed.begin(), seed.end()), rng(Seq) {} -private: - std::seed_seq Seq; - std::default_random_engine rng; protected: - virtual SmallVector randomize() override; - SmallVector Randstruct::perfrandomize(const ASTContext &ctx, - SmallVector fields); virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; }; diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 5ad21e643cf1ef..52bda0dabff8b9 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -144,16 +144,14 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } -SmallVector Randstruct::randomize(SmallVector fields) { +SmallVector randomize(SmallVector fields) { std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } -Randstruct::Randstruct(std::String Seed) { RandstructSeed = Seed; } - -SmallVector Randstruct::perfrandomize(const ASTContext &ctx, +SmallVector perfrandomize(const ASTContext &ctx, SmallVector fields) { // All of the buckets produced by best-effort cache-line algorithm. std::vector> buckets; From fe25c0e5b5fa3709454ab33c234dee89880dab1a Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Tue, 26 Feb 2019 15:34:47 +0000 Subject: [PATCH 77/87] Skip Unions when selecting from randomization There's no harmful effect if we DO randomize a union, however, since all of a union's data members have their offsets set to 0 there's no advantage for our code to run anyway. This way we can spare some CPU cycles in the event that someone adds the randomize attribute to their union. --- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 1f8403867706ca..adb258d55eadd2 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2990,7 +2990,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; - if (ShouldBeRandomized) { + if (ShouldBeRandomized && !D->isUnion()) { Randstruct randstruct; randstruct.reorganizeFields(*this,D); } From 1731e3a97ea413638eccd8f7cff262fcdf5b2c50 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Tue, 26 Feb 2019 16:15:33 +0000 Subject: [PATCH 78/87] Add warning when union has randomize_layout attr --- clang/include/clang/Basic/DiagnosticASTKinds.td | 2 ++ clang/lib/AST/RecordLayoutBuilder.cpp | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index c2a390fa465d81..406325d3677a29 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -343,4 +343,6 @@ def warn_padded_struct_size : Warning< InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; +def warn_randomize_attr_union : Warning< + "union declared with 'randomize_layout' attribute">, InGroup>; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index adb258d55eadd2..11f96294fdc536 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2989,10 +2989,16 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; bool ShouldBeRandomized = D->getAttr() != nullptr; - - if (ShouldBeRandomized && !D->isUnion()) { - Randstruct randstruct; - randstruct.reorganizeFields(*this,D); + if (ShouldBeRandomized) { + // There is no technical benefit to randomizing the fields of a union + // since they all share the same offset of zero. + if (D->isUnion()) { + getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_union); + } + else { + Randstruct randstruct; + randstruct.reorganizeFields(*this,D); + } } if (isMsLayout(*this)) { From e39c92299bc8c5601295925294f566f4b0fd4548 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Tue, 26 Feb 2019 18:29:25 -0800 Subject: [PATCH 79/87] Removed const qualifier from reorganize() and randomize(), since rng is changed on the call to shuffle() --- .../clang/AST/RecordFieldReorganizer.h | 14 ++++++-- clang/lib/AST/RecordFieldReorganizer.cpp | 32 +++++++++---------- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 1f2562b5e389cd..18018adead5975 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -17,6 +17,7 @@ #define LLVM_CLANG_LIB_AST_RECORDFIELDREORGANIZER_H #include "Decl.h" +#include namespace clang { @@ -25,11 +26,11 @@ namespace clang { class RecordFieldReorganizer { public: virtual ~RecordFieldReorganizer() = default; - void reorganizeFields(const ASTContext &C, const RecordDecl *D) const; + void reorganizeFields(const ASTContext &C, const RecordDecl *D); protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, - SmallVector &NewOrder) const = 0; + SmallVector &NewOrder) = 0; private: void commit(const RecordDecl *D, @@ -37,9 +38,16 @@ class RecordFieldReorganizer { }; class Randstruct : public RecordFieldReorganizer { +public: + std::seed_seq Seq; + std::default_random_engine rng; + Randstruct(std::string seed) : Seq(seed.begin(), seed.end()), rng(Seq) {} protected: + SmallVector randomize(SmallVector fields); + SmallVector perfrandomize(const ASTContext &ctx, + SmallVector fields); virtual void reorganize(const ASTContext &C, const RecordDecl *D, - SmallVector &NewOrder) const override; + SmallVector &NewOrder) override; }; } // namespace clang diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 52bda0dabff8b9..825644f3d34cee 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -27,7 +27,7 @@ namespace clang { std::string RandstructSeed = ""; void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, - const RecordDecl *D) const { + const RecordDecl *D) { // Save original fields for asserting later that a subclass hasn't // sabotaged the RecordDecl by removing or adding fields std::set mutateGuard; @@ -67,7 +67,7 @@ class Bucket { public: virtual ~Bucket() = default; /// Returns a randomized version of the bucket. - virtual SmallVector randomize(); + virtual SmallVector randomize(std::default_random_engine rng); /// Checks if an added element would fit in a cache line. virtual bool canFit(size_t size) const; /// Adds a field to the bucket. @@ -87,7 +87,7 @@ class Bucket { /// exceed the size of a cache line. class BitfieldRun : public Bucket { public: - virtual SmallVector randomize() override; + virtual SmallVector randomize(std::default_random_engine rng) override; virtual bool canFit(size_t size) const override; virtual bool isBitfieldRun() const override; }; @@ -95,10 +95,10 @@ class BitfieldRun : public Bucket { // FIXME: Is there a way to detect this? (i.e. on 32bit system vs 64?) const size_t CACHE_LINE = 64; -SmallVector Bucket::randomize() { +SmallVector Bucket::randomize(std::default_random_engine rng) { // FIXME use seed - std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); - auto rng = std::default_random_engine{Seq}; + //std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); + //auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } @@ -132,7 +132,7 @@ bool Bucket::full() const { bool Bucket::empty() const { return size == 0; } -SmallVector BitfieldRun::randomize() { +SmallVector BitfieldRun::randomize(std::default_random_engine rng) { // Keep bit fields adjacent, we will not scramble them. return fields; } @@ -144,15 +144,15 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } -SmallVector randomize(SmallVector fields) { - std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); - auto rng = std::default_random_engine{Seq}; +SmallVector Randstruct::randomize(SmallVector fields) { + //std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); + //auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } -SmallVector perfrandomize(const ASTContext &ctx, - SmallVector fields) { +SmallVector Randstruct::perfrandomize(const ASTContext &ctx, + SmallVector fields) { // All of the buckets produced by best-effort cache-line algorithm. std::vector> buckets; @@ -235,14 +235,14 @@ SmallVector perfrandomize(const ASTContext &ctx, buckets.push_back(std::move(currentBitfieldRun)); } - std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); - auto rng = std::default_random_engine{Seq}; + //std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); + //auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(buckets), std::end(buckets), rng); // Produce the new ordering of the elements from our buckets. SmallVector finalOrder; for (auto &bucket : buckets) { - auto randomized = bucket->randomize(); + auto randomized = bucket->randomize(rng); finalOrder.insert(finalOrder.end(), randomized.begin(), randomized.end()); } @@ -250,7 +250,7 @@ SmallVector perfrandomize(const ASTContext &ctx, } void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, - SmallVector &NewOrder) const { + SmallVector &NewOrder) { SmallVector randomized = perfrandomize(C, NewOrder); NewOrder = randomized; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 1f8403867706ca..2a96a9a21411e6 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2991,7 +2991,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool ShouldBeRandomized = D->getAttr() != nullptr; if (ShouldBeRandomized) { - Randstruct randstruct; + Randstruct randstruct(RandstructSeed); randstruct.reorganizeFields(*this,D); } From b4446bd7effed1f960a48f69ed6e2374eb0fd159 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 27 Feb 2019 22:09:24 +0000 Subject: [PATCH 80/87] Removed unnecessary functions --- clang/include/clang/AST/RecordFieldReorganizer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 48d0b24a8989ac..eb027a35041284 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -34,12 +34,11 @@ class RecordFieldReorganizer { private: void commit(const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const; - bool autostructselect(const SmallVector fields) const; }; class Randstruct : public RecordFieldReorganizer { -public: - //Automatic Structure selection +public: +/// Determines if the Record can be safely and easily randomized based on certain criteria (see implementation). bool isTriviallyRandomizable(const RecordDecl *D) const; protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, From 0a9f6954207cdbf8d5698c490ad7d892272214d0 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Wed, 27 Feb 2019 14:15:42 -0800 Subject: [PATCH 81/87] adding flag --- clang/include/clang/Driver/Options.td | 2 ++ clang/lib/Driver/ToolChains/Clang.cpp | 4 ++++ clang/lib/Frontend/CompilerInvocation.cpp | 3 +++ 3 files changed, 9 insertions(+) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index cb7efbf3edd474..b42a296175e0c6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1751,6 +1751,8 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group, HelpText<"Turn on loop reroller">, Flags<[CC1Option]>; def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group, HelpText<"Turn off loop reroller">; +def thisisaflagpleasechangeme : Flag<["-"], "thisisaflagpleasechangeme">, Group, + HelpText<"Turn off auto selection for struct randomization">, Flags<[CC1Option]>; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 920399c44b1374..f6ca3289d4438f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4411,6 +4411,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(0)); } + if (Arg *A = Args.getLastArg(options::OPT_thisisaflagpleasechangeme)) { + CmdArgs.push_back( "-thisisaflagpleasechangeme" ); + } + // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 249b5d4c690db4..7a672205304a2c 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1674,6 +1674,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (const Arg* A = Args.getLastArg(OPT_frandstruct_seed)) { RandstructSeed = A->getValue(0); } + if (const Arg* A = Args.getLastArg(OPT_thisisaflagpleasechangeme)) { + RandstructFlag = true; + } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); From 97166c8e8d21a713f0766b1f1b66f00e3e2c7dc5 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 27 Feb 2019 23:18:07 +0000 Subject: [PATCH 82/87] Refactored code for better readability --- clang/include/clang/AST/RecordFieldReorganizer.h | 2 +- clang/lib/AST/RecordFieldReorganizer.cpp | 6 ++++-- clang/lib/AST/RecordLayoutBuilder.cpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index eb027a35041284..9f65d85a63dbec 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -39,7 +39,7 @@ class RecordFieldReorganizer { class Randstruct : public RecordFieldReorganizer { public: /// Determines if the Record can be safely and easily randomized based on certain criteria (see implementation). - bool isTriviallyRandomizable(const RecordDecl *D) const; + static bool isTriviallyRandomizable(const RecordDecl *D); protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 88f8c2478e9567..99aa55b89bd240 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -247,8 +247,10 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, SmallVector randomized = perfrandomize(C, NewOrder); NewOrder = randomized; } -bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) const { - +bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) { + /*if(D->getAttr() != nullptr){ + return false; + }*/ for (auto f : D->fields()){ //If an element of the structure does not have a //function type is not a function pointer diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 749659dbc065dc..e58a5f23eae16a 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2986,9 +2986,9 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (Entry) return *Entry; const ASTRecordLayout *NewEntry = nullptr; - Randstruct randstruct; - bool ShouldBeRandomized = randstruct.isTriviallyRandomizable(D) || D->getAttr() != nullptr; + bool ShouldBeRandomized = Randstruct::isTriviallyRandomizable(D) || D->getAttr() != nullptr; if(ShouldBeRandomized){ + Randstruct randstruct; randstruct.reorganizeFields(*this, D); } From 2a220f219a7afb8497b39ffa546bfc600275d1e9 Mon Sep 17 00:00:00 2001 From: Connor Kuehl Date: Wed, 27 Feb 2019 23:41:23 +0000 Subject: [PATCH 83/87] Delete NoRandomizeLayout check This will be checked at our entry point, so we don't need to check this here. --- clang/lib/AST/RecordFieldReorganizer.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 25d1a1bbad3dd4..6bbe272184cd9e 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -254,9 +254,6 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, NewOrder = randomized; } bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) { - /*if(D->getAttr() != nullptr){ - return false; - }*/ for (auto f : D->fields()){ //If an element of the structure does not have a //function type is not a function pointer From 2c5f3ebb276a78d7d08e8c40be4a483f09c7e09f Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 28 Feb 2019 00:24:08 +0000 Subject: [PATCH 84/87] Added changes requested by Nixoncole --- clang/include/clang/Driver/Options.td | 2 +- clang/lib/AST/RecordFieldReorganizer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d4736df95f7fb3..edf714adbf9360 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1753,7 +1753,7 @@ def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group, HelpText<"Turn off loop reroller">; def randstruct_auto : Flag<["-"], "randstruct-auto">, HelpText<"Enable automatic structure selection for field randomization; " - "disabled with no_randomize_layout">, Flags<[CC1Option]>; + "Disable for specific structures with attribute no_randomize_layout">, Flags<[CC1Option]>; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 6bbe272184cd9e..91783fd7cd4151 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -257,7 +257,7 @@ bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) { for (auto f : D->fields()){ //If an element of the structure does not have a //function type is not a function pointer - if(f->getFunctionType() == nullptr){ return false; } + if(f->getFunctionType() == nullptr){ return false; } } return true; } From e3be58537985a2f2cc360ef889fe833040074e60 Mon Sep 17 00:00:00 2001 From: jordan Date: Wed, 27 Feb 2019 20:07:52 -0800 Subject: [PATCH 85/87] generic commit --- clang/lib/AST/RecordFieldReorganizer.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 1507b072e2caff..addecef6f0b929 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -95,9 +95,6 @@ class BitfieldRun : public Bucket { const size_t CACHE_LINE = 64; SmallVector Bucket::randomize(std::default_random_engine rng) { - // FIXME use seed - //std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); - //auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } @@ -144,14 +141,12 @@ bool BitfieldRun::canFit(size_t size) const { bool BitfieldRun::isBitfieldRun() const { return true; } SmallVector Randstruct::randomize(SmallVector fields) { - //std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); - //auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(fields), std::end(fields), rng); return fields; } SmallVector Randstruct::perfrandomize(const ASTContext &ctx, - SmallVector fields) { + SmallVector fields) { // All of the buckets produced by best-effort cache-line algorithm. std::vector> buckets; @@ -234,8 +229,6 @@ SmallVector Randstruct::perfrandomize(const ASTContext &ctx, buckets.push_back(std::move(currentBitfieldRun)); } - //std::seed_seq Seq(RandstructSeed.begin(), RandstructSeed.end()); - //auto rng = std::default_random_engine{Seq}; std::shuffle(std::begin(buckets), std::end(buckets), rng); // Produce the new ordering of the elements from our buckets. From dccaff27c58b2f3e02d685f9375ad87180fa1db8 Mon Sep 17 00:00:00 2001 From: jordan Date: Wed, 27 Feb 2019 22:54:22 -0800 Subject: [PATCH 86/87] generic commit --- clang/lib/AST/RecordLayoutBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index bb100b48bedc18..346592adc374c8 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2996,7 +2996,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_union); } else { - Randstruct randstruct; + Randstruct randstruct(RandstructSeed); randstruct.reorganizeFields(*this,D); } } From 4a6549a67b7caf286509fdb6ab3f2ffabc620b26 Mon Sep 17 00:00:00 2001 From: Jordan Cantrell Date: Thu, 28 Feb 2019 11:10:48 -0800 Subject: [PATCH 87/87] ran clang-format on RecordField/Layout files --- .../clang/AST/RecordFieldReorganizer.h | 9 +- clang/lib/AST/RecordFieldReorganizer.cpp | 24 +- clang/lib/AST/RecordLayoutBuilder.cpp | 355 +++++++++--------- 3 files changed, 192 insertions(+), 196 deletions(-) diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 4b88e6b3bcef24..7e7680b13eccea 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -41,14 +41,17 @@ class Randstruct : public RecordFieldReorganizer { private: std::seed_seq Seq; std::default_random_engine rng; -public: -/// Determines if the Record can be safely and easily randomized based on certain criteria (see implementation). + +public: + /// Determines if the Record can be safely and easily randomized based on + /// certain criteria (see implementation). Randstruct(std::string seed) : Seq(seed.begin(), seed.end()), rng(Seq) {} static bool isTriviallyRandomizable(const RecordDecl *D); + protected: SmallVector randomize(SmallVector fields); SmallVector perfrandomize(const ASTContext &ctx, - SmallVector fields); + SmallVector fields); virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) override; }; diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index addecef6f0b929..a4090908e4cadb 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -66,7 +66,8 @@ class Bucket { public: virtual ~Bucket() = default; /// Returns a randomized version of the bucket. - virtual SmallVector randomize(std::default_random_engine rng); + virtual SmallVector + randomize(std::default_random_engine rng); /// Checks if an added element would fit in a cache line. virtual bool canFit(size_t size) const; /// Adds a field to the bucket. @@ -86,7 +87,8 @@ class Bucket { /// exceed the size of a cache line. class BitfieldRun : public Bucket { public: - virtual SmallVector randomize(std::default_random_engine rng) override; + virtual SmallVector + randomize(std::default_random_engine rng) override; virtual bool canFit(size_t size) const override; virtual bool isBitfieldRun() const override; }; @@ -128,7 +130,8 @@ bool Bucket::full() const { bool Bucket::empty() const { return size == 0; } -SmallVector BitfieldRun::randomize(std::default_random_engine rng) { +SmallVector +BitfieldRun::randomize(std::default_random_engine rng) { // Keep bit fields adjacent, we will not scramble them. return fields; } @@ -145,8 +148,9 @@ SmallVector Randstruct::randomize(SmallVector fields) { return fields; } -SmallVector Randstruct::perfrandomize(const ASTContext &ctx, - SmallVector fields) { +SmallVector +Randstruct::perfrandomize(const ASTContext &ctx, + SmallVector fields) { // All of the buckets produced by best-effort cache-line algorithm. std::vector> buckets; @@ -247,10 +251,12 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, NewOrder = randomized; } bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) { - for (auto f : D->fields()){ - //If an element of the structure does not have a - //function type is not a function pointer - if(f->getFunctionType() == nullptr){ return false; } + for (auto f : D->fields()) { + // If an element of the structure does not have a + // function type is not a function pointer + if (f->getFunctionType() == nullptr) { + return false; + } } return true; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 346592adc374c8..8e1e8417841e06 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -6,8 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/RandstructSeed.h" -#include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Attr.h" @@ -16,7 +14,9 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/RandstructSeed.h" #include "clang/AST/RecordFieldReorganizer.h" +#include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Format.h" @@ -45,7 +45,7 @@ struct BaseSubobjectInfo { bool IsVirtual; /// Bases - Information about the base subobjects. - SmallVector Bases; + SmallVector Bases; /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base /// of this base info (if one exists). @@ -79,8 +79,7 @@ struct ExternalLayout { /// Get the offset of the given field. The external source must provide /// entries for all fields in the record. uint64_t getExternalFieldOffset(const FieldDecl *FD) { - assert(FieldOffsets.count(FD) && - "Field does not have an external offset"); + assert(FieldOffsets.count(FD) && "Field does not have an external offset"); return FieldOffsets[FD]; } @@ -129,8 +128,7 @@ class EmptySubobjectMap { CharUnits Offset, bool PlacingEmptyBase); void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, - const CXXRecordDecl *Class, - CharUnits Offset); + const CXXRecordDecl *Class, CharUnits Offset); void UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset); /// AnyEmptySubobjectsBeyondOffset - Returns whether there are any empty @@ -139,8 +137,8 @@ class EmptySubobjectMap { return Offset <= MaxEmptyClassOffset; } - CharUnits - getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const { + CharUnits getFieldOffset(const ASTRecordLayout &Layout, + unsigned FieldNo) const { uint64_t FieldOffset = Layout.getFieldOffset(FieldNo); assert(FieldOffset % CharWidth == 0 && "Field offset not at char boundary!"); @@ -168,16 +166,15 @@ class EmptySubobjectMap { CharUnits SizeOfLargestEmptySubobject; EmptySubobjectMap(const ASTContext &Context, const CXXRecordDecl *Class) - : Context(Context), CharWidth(Context.getCharWidth()), Class(Class) { - ComputeEmptySubobjectSizes(); + : Context(Context), CharWidth(Context.getCharWidth()), Class(Class) { + ComputeEmptySubobjectSizes(); } /// CanPlaceBaseAtOffset - Return whether the given base class can be placed /// at the given offset. /// Returns false if placing the record will result in two components /// (direct or indirect) of the same type having the same offset. - bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info, - CharUnits Offset); + bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info, CharUnits Offset); /// CanPlaceFieldAtOffset - Return whether a field can be placed at the given /// offset. @@ -228,9 +225,8 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() { } } -bool -EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, - CharUnits Offset) const { +bool EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, + CharUnits Offset) const { // We only need to check empty bases. if (!RD->isEmpty()) return true; @@ -266,9 +262,8 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD, MaxEmptyClassOffset = Offset; } -bool -EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info, - CharUnits Offset) { +bool EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset( + const BaseSubobjectInfo *Info, CharUnits Offset) { // We don't have to keep looking past the maximum offset that's known to // contain an empty class. if (!AnyEmptySubobjectsBeyondOffset(Offset)) @@ -301,7 +296,8 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info, // Traverse all member variables. unsigned FieldNo = 0; for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(), - E = Info->Class->field_end(); I != E; ++I, ++FieldNo) { + E = Info->Class->field_end(); + I != E; ++I, ++FieldNo) { if (I->isBitField()) continue; @@ -348,7 +344,8 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info, // Traverse all member variables. unsigned FieldNo = 0; for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(), - E = Info->Class->field_end(); I != E; ++I, ++FieldNo) { + E = Info->Class->field_end(); + I != E; ++I, ++FieldNo) { if (I->isBitField()) continue; @@ -373,10 +370,9 @@ bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info, return true; } -bool -EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD, - const CXXRecordDecl *Class, - CharUnits Offset) const { +bool EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset( + const CXXRecordDecl *RD, const CXXRecordDecl *Class, + CharUnits Offset) const { // We don't have to keep looking past the maximum offset that's known to // contain an empty class. if (!AnyEmptySubobjectsBeyondOffset(Offset)) @@ -426,9 +422,8 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD, return true; } -bool -EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, - CharUnits Offset) const { +bool EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, + CharUnits Offset) const { // We don't have to keep looking past the maximum offset that's known to // contain an empty class. if (!AnyEmptySubobjectsBeyondOffset(Offset)) @@ -466,9 +461,8 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, return true; } -bool -EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD, - CharUnits Offset) { +bool EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD, + CharUnits Offset) { if (!CanPlaceFieldSubobjectAtOffset(FD, Offset)) return false; @@ -563,7 +557,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD, } } -typedef llvm::SmallPtrSet ClassSetTy; +typedef llvm::SmallPtrSet ClassSetTy; class ItaniumRecordLayoutBuilder { protected: @@ -666,15 +660,14 @@ class ItaniumRecordLayoutBuilder { EmptySubobjectMap *EmptySubobjects) : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()), - UnadjustedAlignment(CharUnits::One()), - UseExternalLayout(false), InferAlignment(false), Packed(false), - IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), - UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0), - MaxFieldAlignment(CharUnits::Zero()), DataSize(0), - NonVirtualSize(CharUnits::Zero()), + UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false), + InferAlignment(false), Packed(false), IsUnion(false), + IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastUnit(0), + LastBitfieldTypeSize(0), MaxFieldAlignment(CharUnits::Zero()), + DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), PrimaryBase(nullptr), - PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), - HasPackedField(false), FirstNearlyEmptyVBase(nullptr) {} + PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false), + FirstNearlyEmptyVBase(nullptr) {} void Layout(const RecordDecl *D); void Layout(const CXXRecordDecl *D); @@ -686,15 +679,13 @@ class ItaniumRecordLayoutBuilder { bool FieldPacked, const FieldDecl *D); void LayoutBitField(const FieldDecl *D); - TargetCXXABI getCXXABI() const { - return Context.getTargetInfo().getCXXABI(); - } + TargetCXXABI getCXXABI() const { return Context.getTargetInfo().getCXXABI(); } /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects. llvm::SpecificBumpPtrAllocator BaseSubobjectInfoAllocator; typedef llvm::DenseMap - BaseSubobjectInfoMapTy; + BaseSubobjectInfoMapTy; /// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases /// of the class we're laying out to their base subobject info. @@ -763,8 +754,8 @@ class ItaniumRecordLayoutBuilder { uint64_t ComputedOffset); void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset, - uint64_t UnpackedOffset, unsigned UnpackedAlign, - bool isPacked, const FieldDecl *D); + uint64_t UnpackedOffset, unsigned UnpackedAlign, + bool isPacked, const FieldDecl *D); DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); @@ -935,8 +926,7 @@ BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo( // Traversing the bases must have created the base info for our primary // virtual base. PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase); - assert(PrimaryVirtualBaseInfo && - "Did not create a primary virtual base!"); + assert(PrimaryVirtualBaseInfo && "Did not create a primary virtual base!"); // Claim the primary virtual base as our primary virtual base. Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo; @@ -954,13 +944,12 @@ void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo( const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl(); // Compute the base subobject info for this base. - BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, - nullptr); + BaseSubobjectInfo *Info = + ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, nullptr); if (IsVirtual) { // ComputeBaseInfo has already added this base for us. - assert(VirtualBaseInfo.count(BaseDecl) && - "Did not add virtual base!"); + assert(VirtualBaseInfo.count(BaseDecl) && "Did not add virtual base!"); } else { // Add the base info to the map of non-virtual bases. assert(!NonVirtualBaseInfo.count(BaseDecl) && @@ -1014,21 +1003,21 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases( LayoutVirtualBase(PrimaryBaseInfo); } else { BaseSubobjectInfo *PrimaryBaseInfo = - NonVirtualBaseInfo.lookup(PrimaryBase); + NonVirtualBaseInfo.lookup(PrimaryBase); assert(PrimaryBaseInfo && "Did not find base info for non-virtual primary base!"); LayoutNonVirtualBase(PrimaryBaseInfo); } - // If this class needs a vtable/vf-table and didn't get one from a - // primary base, add it in now. + // If this class needs a vtable/vf-table and didn't get one from a + // primary base, add it in now. } else if (RD->isDynamicClass()) { assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); CharUnits PtrWidth = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); CharUnits PtrAlign = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); EnsureVTablePointerAlignment(PtrAlign); HasOwnVFPtr = true; setSize(getSize() + PtrWidth); @@ -1158,8 +1147,8 @@ void ItaniumRecordLayoutBuilder::LayoutVirtualBase( // Add its base class offset. assert(!VBases.count(Base->Class) && "vbase offset already exists!"); - VBases.insert(std::make_pair(Base->Class, - ASTRecordLayout::VBaseInfo(Offset, false))); + VBases.insert( + std::make_pair(Base->Class, ASTRecordLayout::VBaseInfo(Offset, false))); AddPrimaryVirtualBaseOffsets(Base, Offset); } @@ -1168,7 +1157,6 @@ CharUnits ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class); - CharUnits Offset; // Query the external layout to see if it provides an offset. @@ -1375,9 +1363,8 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } // Rounds the specified size to have it a multiple of the char size. -static uint64_t -roundUpSizeToCharAlignment(uint64_t Size, - const ASTContext &Context) { +static uint64_t roundUpSizeToCharAlignment(uint64_t Size, + const ASTContext &Context) { uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); return llvm::alignTo(Size, CharAlignment); } @@ -1394,9 +1381,8 @@ void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, // sizeof(T')*8 <= n. QualType IntegralPODTypes[] = { - Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy, - Context.UnsignedLongTy, Context.UnsignedLongLongTy - }; + Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy, + Context.UnsignedLongTy, Context.UnsignedLongLongTy}; QualType Type; for (const QualType &QT : IntegralPODTypes) { @@ -1419,8 +1405,7 @@ void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; if (IsUnion) { - uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, - Context); + uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, Context); setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); FieldOffset = 0; } else { @@ -1540,7 +1525,7 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Compute the next available bit offset. uint64_t FieldOffset = - IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit); + IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit); // Handle targets that don't honor bitfield type alignment. if (!IsMsStruct && !Context.getTargetInfo().useBitFieldTypeAlignment()) { @@ -1550,10 +1535,10 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // The alignment to round up to is the max of the field's natural // alignment and a target-specific fixed value (sometimes zero). unsigned ZeroLengthBitfieldBoundary = - Context.getTargetInfo().getZeroLengthBitfieldBoundary(); + Context.getTargetInfo().getZeroLengthBitfieldBoundary(); FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary); - // If that doesn't apply, just ignore the field alignment. + // If that doesn't apply, just ignore the field alignment. } else { FieldAlign = 1; } @@ -1618,7 +1603,7 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Compute the real offset. if (FieldSize == 0 || (AllowPadding && - (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { + (FieldOffset & (FieldAlign - 1)) + FieldSize > TypeSize)) { FieldOffset = llvm::alignTo(FieldOffset, FieldAlign); } else if (ExplicitFieldAlign && (MaxFieldAlignmentInBits == 0 || @@ -1632,7 +1617,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Repeat the computation for diagnostic purposes. if (FieldSize == 0 || (AllowPadding && - (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) + (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize > + TypeSize)) UnpackedFieldOffset = llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign); else if (ExplicitFieldAlign && @@ -1674,17 +1660,17 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { uint64_t RoundedFieldSize; if (IsMsStruct) { RoundedFieldSize = - (FieldSize ? TypeSize : Context.getTargetInfo().getCharWidth()); + (FieldSize ? TypeSize : Context.getTargetInfo().getCharWidth()); - // Otherwise, allocate just the number of bytes required to store - // the bitfield. + // Otherwise, allocate just the number of bytes required to store + // the bitfield. } else { RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, Context); } setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); - // For non-zero-width bitfields in ms_struct structs, allocate a new - // storage unit if necessary. + // For non-zero-width bitfields in ms_struct structs, allocate a new + // storage unit if necessary. } else if (IsMsStruct && FieldSize) { // We should have cleared UnfilledBitsInLastUnit in every case // where we changed storage units. @@ -1695,9 +1681,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnfilledBitsInLastUnit -= FieldSize; LastBitfieldTypeSize = TypeSize; - // Otherwise, bump the data size up to include the bitfield, - // including padding up to char alignment, and then remember how - // bits we didn't use. + // Otherwise, bump the data size up to include the bitfield, + // including padding up to char alignment, and then remember how + // bits we didn't use. } else { uint64_t NewSizeInBits = FieldOffset + FieldSize; uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); @@ -1734,8 +1720,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, LastBitfieldTypeSize = 0; bool FieldPacked = Packed || D->hasAttr(); - CharUnits FieldOffset = - IsUnion ? CharUnits::Zero() : getDataSize(); + CharUnits FieldOffset = IsUnion ? CharUnits::Zero() : getDataSize(); CharUnits FieldSize; CharUnits FieldAlign; @@ -1745,17 +1730,17 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, // Flexible array members don't have any size, but they // have to be aligned appropriately for their element type. FieldSize = CharUnits::Zero(); - const ArrayType* ATy = Context.getAsArrayType(D->getType()); + const ArrayType *ATy = Context.getAsArrayType(D->getType()); FieldAlign = Context.getTypeAlignInChars(ATy->getElementType()); } else if (const ReferenceType *RT = D->getType()->getAs()) { unsigned AS = Context.getTargetAddressSpace(RT->getPointeeType()); - FieldSize = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS)); - FieldAlign = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(AS)); + FieldSize = Context.toCharUnitsFromBits( + Context.getTargetInfo().getPointerWidth(AS)); + FieldAlign = Context.toCharUnitsFromBits( + Context.getTargetInfo().getPointerAlign(AS)); } else { std::pair FieldInfo = - Context.getTypeInfoInChars(D->getType()); + Context.getTypeInfoInChars(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; @@ -1809,7 +1794,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, if (FieldPacked) FieldAlign = CharUnits::One(); CharUnits MaxAlignmentInChars = - Context.toCharUnitsFromBits(D->getMaxAlignment()); + Context.toCharUnitsFromBits(D->getMaxAlignment()); FieldAlign = std::max(FieldAlign, MaxAlignmentInChars); UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars); @@ -1825,7 +1810,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, if (UseExternalLayout) { FieldOffset = Context.toCharUnitsFromBits( - updateExternalFieldOffset(D, Context.toBits(FieldOffset))); + updateExternalFieldOffset(D, Context.toBits(FieldOffset))); if (!IsUnion && EmptySubobjects) { // Record the fact that we're placing a field at this offset. @@ -1884,8 +1869,7 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // array of zero-length, remains of Size 0 if (RD->isEmpty()) setSize(CharUnits::One()); - } - else + } else setSize(CharUnits::One()); } @@ -1923,8 +1907,7 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { InBits = false; } Diag(RD->getLocation(), diag::warn_padded_struct_size) - << Context.getTypeDeclType(RD) - << PadSize + << Context.getTypeDeclType(RD) << PadSize << (InBits ? 1 : 0); // (byte|bit) } @@ -1981,10 +1964,14 @@ ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, /// \returns diagnostic %select index. static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) { switch (Tag) { - case TTK_Struct: return 0; - case TTK_Interface: return 1; - case TTK_Class: return 2; - default: llvm_unreachable("Invalid tag kind for field padding diagnostic!"); + case TTK_Struct: + return 0; + case TTK_Interface: + return 1; + case TTK_Class: + return 2; + default: + llvm_unreachable("Invalid tag kind for field padding diagnostic!"); } } @@ -2014,20 +2001,18 @@ void ItaniumRecordLayoutBuilder::CheckFieldPadding( if (D->getIdentifier()) Diag(D->getLocation(), diag::warn_padded_struct_field) << getPaddingDiagFromTagKind(D->getParent()->getTagKind()) - << Context.getTypeDeclType(D->getParent()) - << PadSize + << Context.getTypeDeclType(D->getParent()) << PadSize << (InBits ? 1 : 0) // (byte|bit) << D->getIdentifier(); else Diag(D->getLocation(), diag::warn_padded_struct_anon_field) << getPaddingDiagFromTagKind(D->getParent()->getTagKind()) - << Context.getTypeDeclType(D->getParent()) - << PadSize + << Context.getTypeDeclType(D->getParent()) << PadSize << (InBits ? 1 : 0); // (byte|bit) - } - if (isPacked && Offset != UnpackedOffset) { - HasPackedField = true; - } + } + if (isPacked && Offset != UnpackedOffset) { + HasPackedField = true; + } } static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, @@ -2051,7 +2036,7 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, return nullptr; bool allowInlineFunctions = - Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline(); + Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline(); for (const CXXMethodDecl *MD : RD->methods()) { if (!MD->isVirtual()) @@ -2259,9 +2244,11 @@ struct MicrosoftRecordLayoutBuilder { }; typedef llvm::DenseMap BaseOffsetsMapTy; MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {} + private: MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete; void operator=(const MicrosoftRecordLayoutBuilder &) = delete; + public: void layout(const RecordDecl *RD); void cxxLayout(const CXXRecordDecl *RD); @@ -2384,15 +2371,15 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( // the alignment in the case of pragam pack. Note that the required alignment // doesn't actually apply to the struct alignment at this point. Alignment = std::max(Alignment, Info.Alignment); - RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment()); + RequiredAlignment = + std::max(RequiredAlignment, Layout.getRequiredAlignment()); Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment()); Info.Size = Layout.getNonVirtualSize(); return Info; } MicrosoftRecordLayoutBuilder::ElementInfo -MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( - const FieldDecl *FD) { +MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(const FieldDecl *FD) { // Get the alignment of the field type's natural alignment, ignore any // alignment attributes. ElementInfo Info; @@ -2415,8 +2402,8 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( FD->getType()->getBaseElementTypeUnsafe()->getAs()) { auto const &Layout = Context.getASTRecordLayout(RT->getDecl()); EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject(); - FieldRequiredAlignment = std::max(FieldRequiredAlignment, - Layout.getRequiredAlignment()); + FieldRequiredAlignment = + std::max(FieldRequiredAlignment, Layout.getRequiredAlignment()); } // Capture required alignment as a side-effect. RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment); @@ -2478,10 +2465,11 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { MaxFieldAlignment = CharUnits::Zero(); // Honor the default struct packing maximum alignment flag. if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) - MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); + MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); // Honor the packing attribute. The MS-ABI ignores pragma pack if its larger // than the pointer size. - if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr()){ + if (const MaxFieldAlignmentAttr *MFAA = + RD->getAttr()) { unsigned PackedAlignment = MFAA->getAlignment(); if (PackedAlignment <= Context.getTargetInfo().getPointerWidth(0)) MaxFieldAlignment = Context.toCharUnitsFromBits(PackedAlignment); @@ -2498,8 +2486,8 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { External.BaseOffsets, External.VirtualBaseOffsets); } -void -MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) { +void MicrosoftRecordLayoutBuilder::initializeCXXLayout( + const CXXRecordDecl *RD) { EndsWithZeroSizedObject = false; LeadsWithZeroSizedBase = false; HasOwnVFPtr = false; @@ -2517,8 +2505,8 @@ MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) { PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment); } -void -MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { +void MicrosoftRecordLayoutBuilder::layoutNonVirtualBases( + const CXXRecordDecl *RD) { // The MS-ABI lays out all bases that contain leading vfptrs before it lays // out any bases that do not contain vfptrs. We implement this as two passes // over the bases. This approach guarantees that the primary base is laid out @@ -2606,8 +2594,7 @@ static bool recordUsesEBO(const RecordDecl *RD) { } void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( - const CXXRecordDecl *RD, - const CXXRecordDecl *BaseDecl, + const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl, const ASTRecordLayout &BaseLayout, const ASTRecordLayout *&PreviousBaseLayout) { // Insert padding between two bases if the left first one is zero sized or @@ -2713,8 +2700,8 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { } } -void -MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { +void MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField( + const FieldDecl *FD) { // Zero-width bitfields are ignored unless they follow a non-zero-width // bitfield. if (!LastFieldIsNonZeroWidthBitfield) { @@ -2840,8 +2827,8 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { assert(BaseOffset >= Size && "base offset already allocated"); - VBases.insert(std::make_pair(BaseDecl, - ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); + VBases.insert(std::make_pair( + BaseDecl, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); Size = BaseOffset + BaseLayout.getNonVirtualSize(); PreviousBaseLayout = &BaseLayout; } @@ -2881,10 +2868,9 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { // Recursively walks the non-virtual bases of a class and determines if any of // them are in the bases with overridden methods set. -static bool -RequiresVtordisp(const llvm::SmallPtrSetImpl & - BasesWithOverriddenMethods, - const CXXRecordDecl *RD) { +static bool RequiresVtordisp(const llvm::SmallPtrSetImpl + &BasesWithOverriddenMethods, + const CXXRecordDecl *RD) { if (BasesWithOverriddenMethods.count(RD)) return true; // If any of a virtual bases non-virtual bases (recursively) requires a @@ -2973,7 +2959,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // until we *finish* parsing the definition. if (D->hasExternalLexicalStorage() && !D->getDefinition()) - getExternalSource()->CompleteType(const_cast(D)); + getExternalSource()->CompleteType(const_cast(D)); D = D->getDefinition(); assert(D && "Cannot get layout of forward declarations!"); @@ -2984,20 +2970,23 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // Note that we can't save a reference to the entry because this function // is recursive. const ASTRecordLayout *Entry = ASTRecordLayouts[D]; - if (Entry) return *Entry; + if (Entry) + return *Entry; const ASTRecordLayout *NewEntry = nullptr; - bool ShouldBeRandomized = (RandstructAutoSelect && Randstruct::isTriviallyRandomizable(D)) || D->getAttr() != nullptr; + bool ShouldBeRandomized = + (RandstructAutoSelect && Randstruct::isTriviallyRandomizable(D)) || + D->getAttr() != nullptr; if (ShouldBeRandomized) { // There is no technical benefit to randomizing the fields of a union // since they all share the same offset of zero. if (D->isUnion()) { - getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_union); - } - else { + getDiagnostics().Report(D->getLocation(), + diag::warn_randomize_attr_union); + } else { Randstruct randstruct(RandstructSeed); - randstruct.reorganizeFields(*this,D); + randstruct.reorganizeFields(*this, D); } } @@ -3007,19 +2996,17 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Builder.cxxLayout(RD); NewEntry = new (*this) ASTRecordLayout( *this, Builder.Size, Builder.Alignment, Builder.Alignment, - Builder.RequiredAlignment, - Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase, - Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets, - Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(), - Builder.PrimaryBase, false, Builder.SharedVBPtrBase, - Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase, - Builder.Bases, Builder.VBases); + Builder.RequiredAlignment, Builder.HasOwnVFPtr, + Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset, + Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize, + Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase, false, + Builder.SharedVBPtrBase, Builder.EndsWithZeroSizedObject, + Builder.LeadsWithZeroSizedBase, Builder.Bases, Builder.VBases); } else { Builder.layout(D); NewEntry = new (*this) ASTRecordLayout( *this, Builder.Size, Builder.Alignment, Builder.Alignment, - Builder.RequiredAlignment, - Builder.Size, Builder.FieldOffsets); + Builder.RequiredAlignment, Builder.Size, Builder.FieldOffsets); } } else { if (const auto *RD = dyn_cast(D)) { @@ -3039,7 +3026,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { CharUnits NonVirtualSize = skipTailPadding ? DataSize : Builder.NonVirtualSize; NewEntry = new (*this) ASTRecordLayout( - *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment, + *this, Builder.getSize(), Builder.Alignment, + Builder.UnadjustedAlignment, /*RequiredAlignment : used by MS-ABI)*/ Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(), CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets, @@ -3052,7 +3040,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Builder.Layout(D); NewEntry = new (*this) ASTRecordLayout( - *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment, + *this, Builder.getSize(), Builder.Alignment, + Builder.UnadjustedAlignment, /*RequiredAlignment : used by MS-ABI)*/ Builder.Alignment, Builder.getSize(), Builder.FieldOffsets); } @@ -3068,7 +3057,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { return *NewEntry; } -const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) { +const CXXMethodDecl * +ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) { if (!getTargetInfo().getCXXABI().hasKeyFunctions()) return nullptr; @@ -3086,7 +3076,7 @@ const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) // Store it back if it changed. if (Entry.isOffset() || Entry.isValid() != bool(Result)) - KeyFunctions[RD] = const_cast(Result); + KeyFunctions[RD] = const_cast(Result); return cast_or_null(Result); } @@ -3102,7 +3092,8 @@ void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) { auto I = Map.find(Method->getParent()); // If it's not cached, there's nothing to do. - if (I == Map.end()) return; + if (I == Map.end()) + return; // If it is cached, check whether it's the target method, and if so, // remove it from the cache. Note, the call to 'get' might invalidate @@ -3158,8 +3149,8 @@ uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID, // directly. unsigned Index = 0; - for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) { + for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); IVD; + IVD = IVD->getNextIvar()) { if (Ivar == IVD) break; ++Index; @@ -3179,13 +3170,13 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const { // Retrieve the definition if (D->hasExternalLexicalStorage() && !D->getDefinition()) - getExternalSource()->CompleteType(const_cast(D)); + getExternalSource()->CompleteType(const_cast(D)); D = D->getDefinition(); assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!"); // Look up this layout, if already laid out, return what we have. const ObjCContainerDecl *Key = - Impl ? (const ObjCContainerDecl*) Impl : (const ObjCContainerDecl*) D; + Impl ? (const ObjCContainerDecl *)Impl : (const ObjCContainerDecl *)D; if (const ASTRecordLayout *Entry = ObjCLayouts[Key]) return *Entry; @@ -3203,22 +3194,18 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr); Builder.Layout(D); - const ASTRecordLayout *NewEntry = - new (*this) ASTRecordLayout(*this, Builder.getSize(), - Builder.Alignment, - Builder.UnadjustedAlignment, - /*RequiredAlignment : used by MS-ABI)*/ - Builder.Alignment, - Builder.getDataSize(), - Builder.FieldOffsets); + const ASTRecordLayout *NewEntry = new (*this) ASTRecordLayout( + *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment, + /*RequiredAlignment : used by MS-ABI)*/ + Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets); ObjCLayouts[Key] = NewEntry; return *NewEntry; } -static void PrintOffset(raw_ostream &OS, - CharUnits Offset, unsigned IndentLevel) { +static void PrintOffset(raw_ostream &OS, CharUnits Offset, + unsigned IndentLevel) { OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity()); OS.indent(IndentLevel * 2); } @@ -3247,17 +3234,14 @@ static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel) { } static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, - const ASTContext &C, - CharUnits Offset, - unsigned IndentLevel, - const char* Description, - bool PrintSizeInfo, - bool IncludeVirtualBases) { + const ASTContext &C, CharUnits Offset, + unsigned IndentLevel, const char *Description, + bool PrintSizeInfo, bool IncludeVirtualBases) { const ASTRecordLayout &Layout = C.getASTRecordLayout(RD); auto CXXRD = dyn_cast(RD); PrintOffset(OS, Offset, IndentLevel); - OS << C.getTypeDeclType(const_cast(RD)).getAsString(); + OS << C.getTypeDeclType(const_cast(RD)).getAsString(); if (Description) OS << ' ' << Description; if (CXXRD && CXXRD->isEmpty()) @@ -3294,8 +3278,9 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, // Sort nvbases by offset. std::stable_sort(Bases.begin(), Bases.end(), [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { - return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); - }); + return Layout.getBaseClassOffset(L) < + Layout.getBaseClassOffset(R); + }); // Dump (non-virtual) bases for (const CXXRecordDecl *Base : Bases) { @@ -3315,12 +3300,12 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, // Dump fields. uint64_t FieldNo = 0; - for (RecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); I != E; ++I, ++FieldNo) { + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I, ++FieldNo) { const FieldDecl &Field = **I; uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo); CharUnits FieldOffset = - Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits); + Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits); // Recursively dump fields of record type. if (auto RT = Field.getType()->getAs()) { @@ -3345,7 +3330,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, // Dump virtual bases. if (CXXRD && IncludeVirtualBases) { const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps = - Layout.getVBaseOffsetsMap(); + Layout.getVBaseOffsetsMap(); for (const CXXBaseSpecifier &Base : CXXRD->vbases()) { assert(Base.isVirtual() && "Found non-virtual class!"); @@ -3359,14 +3344,16 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, } DumpRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel, - VBase == Layout.getPrimaryBase() ? - "(primary virtual base)" : "(virtual base)", + VBase == Layout.getPrimaryBase() + ? "(primary virtual base)" + : "(virtual base)", /*PrintSizeInfo=*/false, /*IncludeVirtualBases=*/false); } } - if (!PrintSizeInfo) return; + if (!PrintSizeInfo) + return; PrintIndentNoOffset(OS, IndentLevel - 1); OS << "[sizeof=" << Layout.getSize().getQuantity(); @@ -3383,12 +3370,11 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, OS << "]\n"; } -void ASTContext::DumpRecordLayout(const RecordDecl *RD, - raw_ostream &OS, +void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple) const { if (!Simple) { ::DumpRecordLayout(OS, RD, *this, CharUnits(), 0, nullptr, - /*PrintSizeInfo*/true, + /*PrintSizeInfo*/ true, /*IncludeVirtualBases=*/true); return; } @@ -3410,7 +3396,8 @@ void ASTContext::DumpRecordLayout(const RecordDecl *RD, OS << " Alignment:" << toBits(Info.getAlignment()) << "\n"; OS << " FieldOffsets: ["; for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) { - if (i) OS << ", "; + if (i) + OS << ", "; OS << Info.getFieldOffset(i); } OS << "]>\n";