Skip to content

Commit

Permalink
Added basic implementation of auto selection for strucutres of only f…
Browse files Browse the repository at this point in the history
…unction pointers
  • Loading branch information
Jafosterja committed Feb 23, 2019
1 parent 753b226 commit e0cfd8a
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 3 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/AST/RecordFieldReorganizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class RecordFieldReorganizer {
private:
void commit(const RecordDecl *D,
SmallVectorImpl<Decl *> &NewFieldOrder) const;
bool autostructselect(const SmallVector<Decl *,64> fields) const;
};

class Randstruct : public RecordFieldReorganizer {
Expand Down
21 changes: 19 additions & 2 deletions clang/lib/AST/RecordFieldReorganizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C,
mutateGuard.insert(f);
fields.push_back(f);
}

if(D->getAttr<RandomizeLayoutAttr>() == nullptr){
if(!autostructselect(fields)){
return;
}
}
// Now allow subclass implementations to reorder the fields
reorganize(C, D, fields);

Expand All @@ -50,7 +54,20 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C,

commit(D, fields);
}

bool RecordFieldReorganizer::autostructselect(const SmallVector<Decl *, 64> 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<Decl *> &NewFieldOrder) const {
Decl *First, *Last;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2988,7 +2988,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
const ASTRecordLayout *NewEntry = nullptr;

bool ShouldBeRandomized = D->getAttr<RandomizeLayoutAttr>() != nullptr;
if (ShouldBeRandomized) {
if (true) {
Randstruct randstruct;
randstruct.reorganizeFields(*this, D);
}
Expand Down

1 comment on commit e0cfd8a

@connorkuehl
Copy link

@connorkuehl connorkuehl commented on e0cfd8a Feb 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Suggestions:

  • add a public, static method to the Randstruct class with a cool name like shouldAutoSelect() or isTriviallyRandomizable() -- I think I like the second one better. It'll take a const RecordDecl *D as an argument.

Its implementation cold probably look a little something like this:

// Once Cole's PR lands, we can disqualify if it has `no_randomize_layout`
if (D->getAttr<NoRandomizeLayoutAttr>() != nullptr) { return false; }

for (auto field : D->fields()) {
    if (!field->getFunctionType()) { return false; }
}

return true;

We might even extract that loop out to a private static function called Randstruct::isAllFunctionPointers(const RecordDecl *D) if our criteria for automatic structure selection grows and we need to keep the code tidy.

  • Then our entry point code can return to:
   bool ShouldBeRandomized = Randstruct::isTriviallyRandomizable(D) || D->getAttr<RandomizeLayoutAttr>() != nullptr; 

Please sign in to comment.