Skip to content

Commit

Permalink
change frontend rewriter to better handle anonymous struct/union
Browse files Browse the repository at this point in the history
Kernel Commit 29e48ce87f1e ("task_struct: Allow randomized layout")
(https://patchwork.kernel.org/patch/9797817/)
permits to randomize a section of kernel task_struct data
structure. This only takes effect when CONFIG_GCC_PLUGINS and
CONFIG_GCC_PLUGIN_RANDSTRUCT are set.

When randomization does not happen, an anonymous struct
is introduced in task_struct data structure by gcc when compiling
the kernel. To make field offset compatible, task_struct will
have the same anonymous struct. The patch is at
http://www.spinics.net/lists/kernel/msg2644958.html.
Otherwise, bpf program may get wrong data from the kernel.

Currently, bcc bpf_probe_read rewriter does not support
anonymous struct/union. For example, with the above
compiler-clang.h patch, examples/tracing/task_switch.py
will have the following error:
  /virtual/main.c:16:18: error: internal error: opLoc is invalid while preparing probe rewrite
    key.prev_pid = prev->pid;
                   ^

For anonymous structure, opcode source location ("->") is not available
and hence the above failure. We could use memberLoc ("pid") which is
available for anonymous struct/union. For example, for
  struct sock *skp; ...; u32 saddr = skp->__sk_common.skc_rcv_saddr;
The old way for bpf_probe_read rewrite:
  bpf_probe_read(&_val, sizeof(_val), (u64)skp + offsetof(struct sock, __sk_common.skc_rcv_saddr));
The new way:
  bpf_probe_read(&_val, sizeof(_val), (u64)&skp->__sk_common.skc_rcv_saddr);

The new way is similar to what typical bpf programs may do manually.

Signed-off-by: Yonghong Song <yhs@fb.com>
  • Loading branch information
yonghong-song authored and drzaeus77 committed Nov 9, 2017
1 parent 1d0f292 commit 94d15bc
Showing 1 changed file with 7 additions and 8 deletions.
15 changes: 7 additions & 8 deletions src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -211,33 +211,32 @@ bool ProbeVisitor::VisitMemberExpr(MemberExpr *E) {
return true;

Expr *base;
SourceLocation rhs_start, op;
SourceLocation rhs_start, member;
bool found = false;
for (MemberExpr *M = E; M; M = dyn_cast<MemberExpr>(M->getBase())) {
memb_visited_.insert(M);
rhs_start = M->getLocEnd();
base = M->getBase();
op = M->getOperatorLoc();
member = M->getMemberLoc();
if (M->isArrow()) {
found = true;
break;
}
}
if (!found)
return true;
if (op.isInvalid()) {
error(base->getLocEnd(), "internal error: opLoc is invalid while preparing probe rewrite");
if (member.isInvalid()) {
error(base->getLocEnd(), "internal error: MemberLoc is invalid while preparing probe rewrite");
return false;
}
string rhs = rewriter_.getRewrittenText(expansionRange(SourceRange(rhs_start, E->getLocEnd())));
string base_type = base->getType()->getPointeeType().getAsString();
string pre, post;
pre = "({ typeof(" + E->getType().getAsString() + ") _val; memset(&_val, 0, sizeof(_val));";
pre += " bpf_probe_read(&_val, sizeof(_val), (u64)";
post = " + offsetof(" + base_type + ", " + rhs + ")";
post += "); _val; })";
pre += " bpf_probe_read(&_val, sizeof(_val), (u64)&";
post = rhs + "); _val; })";
rewriter_.InsertText(E->getLocStart(), pre);
rewriter_.ReplaceText(expansionRange(SourceRange(op, E->getLocEnd())), post);
rewriter_.ReplaceText(expansionRange(SourceRange(member, E->getLocEnd())), post);
return true;
}

Expand Down

0 comments on commit 94d15bc

Please sign in to comment.