Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restrict rewrite of unary operators to dereference operator #1005

Merged
merged 1 commit into from
Mar 7, 2017

Conversation

pchaigno
Copy link
Contributor

@pchaigno pchaigno commented Feb 23, 2017

This pull request limits the rewriting of unary operators to the
dereference operator and fixes #344.

Since the whole expression, unary operator included, is replaced by a
call to bpf_probe_read, the dereference operator is currently the
only unary operator properly rewritten anyway. When rewriting an
increment expression (++val) for instance, the increment operator is
lost in translation:

// struct file *val = ++file;
struct file *val = ({ typeof(struct file *) _val;
                      memset(&_val, 0, sizeof(_val));
                      bpf_probe_read(&_val, sizeof(_val), (u64)file);
                      _val; });

Restricting the rewriting to dereference operators fixes #344 because
bcc won't try anymore to translate the logical negation in:
!file->f_op->read_iter.

/cc @drzaeus77 @brendangregg

@pchaigno pchaigno force-pushed the rewrite-only-deref branch 2 times, most recently from a942107 to 84e5fef Compare February 27, 2017 21:28
@pchaigno pchaigno force-pushed the rewrite-only-deref branch 2 times, most recently from a069c28 to 9dc01d5 Compare March 5, 2017 09:21
@pchaigno
Copy link
Contributor Author

pchaigno commented Mar 5, 2017

I've added a test case in test_clang.py based on @brendangregg's code in #344.

@4ast
Copy link
Member

4ast commented Mar 5, 2017

cc @drzaeus77

@drzaeus77
Copy link
Collaborator

I know I played with it once, but can you refresh my memory on whether clang treats (*p). and p-> the same, and whether that would be a problem here?

Also, please rebase since there is now a conflict in test_clang.py.

Since the whole expression, unary operator included, is replaced by a
call to bpf_probe_read, the dereference operator is currently the
only unary operator properly rewritten. When rewriting an increment
expression (++val) for instance, the increment operator is lost in
translation.

Trying to rewrite all unary operators sometimes confuses bcc and
results in improper code, for instance when trying to rewrite a
logical negation.
@pchaigno
Copy link
Contributor Author

pchaigno commented Mar 6, 2017

Clang sees p-> as a MemberExpr (taken care of by bcc rewriter in b_frontend_action.cc#L202-L218) whereas it sees *p as a UnaryOperator of opcode UO_Deref (taken care of in b_frontend_action.cc#L219-L256).

So the rewrite isn't equivalent between (*p). and p->:

return !(*file).f_op;
return !file->f_op;

is rewritten into:

return !(({ typeof(struct file) _val;
            memset(&_val, 0, sizeof(_val));
            bpf_probe_read(&_val, sizeof(_val), (u64)file);
            _val; })).f_op;
return !({ typeof(const struct file_operations *) _val;
            memset(&_val, 0, sizeof(_val));
            bpf_probe_read(&_val, sizeof(_val), (u64)file + offsetof(struct file, f_op));
            _val; });

The new test case (!file->f_op->read_iter) serves as a check on the ! more than on the ->s. With this pull request, bcc doesn't try to replace the negation anymore (while the ->s were already correctly replaced).

@drzaeus77
Copy link
Collaborator

Ok, please proceed with the rebase.

@drzaeus77
Copy link
Collaborator

[buildbot, test this please]

@drzaeus77 drzaeus77 merged commit 575b3e5 into iovisor:master Mar 7, 2017
@pchaigno pchaigno deleted the rewrite-only-deref branch March 7, 2017 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

possible rewriter issue with f_op
3 participants