Skip to content

Commit

Permalink
Support identifying btf type
Browse files Browse the repository at this point in the history
k(ret)func and iter are btf-based tracing, which can detect whether dereferencing is safe through btf, so dereferencing does not need to call the helper function bpf_probe_read. This patch mainly modifies the semantic and codegen modules

semantic:
- Handle the ctx of iter, mark is_btftype as true
- Handle the retval of kretfunc, mark is_btftype as true
- When dealing with ArrayAccess, Unop, FieldAccess, inherit is_btftype attribute

codegen:
- If it is a string type, use CREATE_MEMCPY directly to load the data
- For other types, load data through CreateDatastructElemLoad instead of CreateProbeRead

Signed-off-by: Shuyi Cheng <chengshuyi@linux.alibaba.com>
  • Loading branch information
chengshuyi authored and viktormalik committed May 19, 2023
1 parent 31d7a35 commit c2c3ab9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/ast/passes/codegen_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1852,6 +1852,7 @@ void CodegenLLVM::visit(FieldAccess &acc)
bool is_tparg = type.is_tparg;
bool is_internal = type.is_internal;
bool is_funcarg = type.is_funcarg;
bool is_btftype = type.is_btftype;
assert(type.IsRecordTy() || type.IsTupleTy());

if (type.is_funcarg)
Expand Down Expand Up @@ -1893,6 +1894,7 @@ void CodegenLLVM::visit(FieldAccess &acc)
type.is_tparg = is_tparg;
type.is_internal = is_internal;
type.is_funcarg = is_funcarg;
type.is_btftype = is_btftype;
// Restore the addrspace info
// struct MyStruct { const int* a; }; $s = (struct MyStruct *)arg0; $s->a
type.SetAS(addrspace);
Expand Down Expand Up @@ -3530,23 +3532,30 @@ void CodegenLLVM::probereadDatastructElem(Value *src_data,
{
// Read data onto stack
AllocaInst *dst = b_.CreateAllocaBPF(elem_type, temp_name);
b_.CreateProbeRead(ctx_, dst, elem_type, src, loc, data_type.GetAS());
if (elem_type.IsStringTy() && data_type.is_btftype)
{
b_.CREATE_MEMCPY(dst, src, elem_type.GetSize(), 1);
}
else
{
b_.CreateProbeRead(ctx_, dst, elem_type, src, loc, data_type.GetAS());
}
expr_ = dst;
expr_deleter_ = [this, dst]() { b_.CreateLifetimeEnd(dst); };
}
else
{
// Read data onto stack
if (data_type.IsCtxAccess())
if (data_type.IsCtxAccess() || data_type.is_btftype)
{
expr_ = b_.CreateDatastructElemLoad(
elem_type,
b_.CreateIntToPtr(src, dst_type->getPointerTo()),
true,
data_type.GetAS());

// check context access for iter probes (required by kernel)
if (probetype(current_attach_point_->provider) == ProbeType::iter)
if (data_type.IsCtxAccess() &&
probetype(current_attach_point_->provider) == ProbeType::iter)
{
Function *parent = b_.GetInsertBlock()->getParent();
BasicBlock *pred_false_block = BasicBlock::Create(module_->getContext(),
Expand Down
13 changes: 13 additions & 0 deletions src/ast/passes/semantic_analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ void SemanticAnalyser::visit(Builtin &builtin)
CreateRecord(type, bpftrace_.structs.Lookup(type)),
AddrSpace::kernel);
builtin.type.MarkCtxAccess();
builtin.type.is_btftype = true;
}
else
{
Expand Down Expand Up @@ -331,7 +332,10 @@ void SemanticAnalyser::visit(Builtin &builtin)
auto it = ap_args_.find("$retval");

if (it != ap_args_.end())
{
builtin.type = it->second;
builtin.type.is_btftype = true;
}
else
LOG(ERROR, builtin.loc, err_) << "Can't find a field $retval";
}
Expand Down Expand Up @@ -1622,6 +1626,7 @@ void SemanticAnalyser::visit(ArrayAccess &arr)
else
arr.type = CreateNone();
arr.type.is_internal = type.is_internal;
arr.type.is_btftype = type.is_btftype;
arr.type.SetAS(type.GetAS());
}

Expand Down Expand Up @@ -1992,6 +1997,7 @@ void SemanticAnalyser::visit(Unop &unop)
unop.type.is_funcarg = type.is_funcarg;
unop.type.is_tparg = type.is_tparg;
}
unop.type.is_btftype = type.is_btftype;
unop.type.SetAS(type.GetAS());
}
else if (type.IsRecordTy())
Expand Down Expand Up @@ -2178,6 +2184,12 @@ void SemanticAnalyser::visit(FieldAccess &acc)
{
if (acc.type.IsNoneTy())
LOG(ERROR, acc.loc, err_) << acc.field << " has unsupported type";

ProbeType probetype = single_provider_type();
if (probetype == ProbeType::kfunc || probetype == ProbeType::kretfunc)
{
acc.type.is_btftype = true;
}
}
}
else
Expand Down Expand Up @@ -2268,6 +2280,7 @@ void SemanticAnalyser::visit(FieldAccess &acc)
acc.type.MarkCtxAccess();
}
acc.type.is_internal = type.is_internal;
acc.type.is_btftype = type.is_btftype;
acc.type.SetAS(acc.expr->type.GetAS());

// The kernel uses the first 8 bytes to store `struct pt_regs`. Any
Expand Down
2 changes: 2 additions & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class SizedType
bool is_internal = false;
bool is_tparg = false;
bool is_funcarg = false;
bool is_btftype = false;
int funcarg_idx = -1;

private:
Expand All @@ -141,6 +142,7 @@ class SizedType
is_internal,
is_tparg,
is_funcarg,
is_btftype,
funcarg_idx,
size_,
is_signed_,
Expand Down

0 comments on commit c2c3ab9

Please sign in to comment.