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

Support non-map print() #1381

Merged
merged 9 commits into from
Jun 29, 2020
Merged

Support non-map print() #1381

merged 9 commits into from
Jun 29, 2020

Conversation

danobi
Copy link
Member

@danobi danobi commented Jun 12, 2020

This implements non-map prints as described in #356.

Note that non-map print()s are synchronous, meaning they do not
work the same as map print()s. I think this is a pretty nice feature.

Example:

# bpftrace -e 'BEGIN { $t = (1, "string"); print(123); print($t); print(comm) }'
Attaching 1 probe...
123
(1, string)
bpftrace
^C

We have a growing number of types in the type system so I may have
missed a corner case somewhere. I think I got most of it right, though.

This closes #356.

Checklist
  • Language changes are updated in docs/reference_guide.md
  • User-visible and non-trivial changes updated in CHANGELOG.md

@danobi danobi force-pushed the print_anything branch 4 times, most recently from 2fedd7a to 03c4b16 Compare June 13, 2020 00:54
@mmisono
Copy link
Collaborator

mmisono commented Jun 13, 2020

Looks very useful. I found some issues:

  • comm in a tuple is not correct.
% sudo ./src/bpftrace -e 'BEGIN { print(comm); print((1,comm)); }'
Attaching 1 probe...
bpftrace
(1, 7u)
^C

Consulting the generated IR, it seems this is the same bug as #1332. The buffer holding the result of bpf_get_current_comm is overwritten before use. (The async id of print is 30007 = 0x7537 = 'u' and '7'.) This bug is really annoying..

$ sudo ./src/bpftrace -e 'BEGIN { print(exit()); }'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==20081==ERROR: AddressSanitizer: SEGV on unknown address 0x000000004e71 (pc 0x7f39655c2080 bp 0x7ffc781c73b0 sp 0x7ffc781c72c8 T0)
==20081==The signal is caused by a READ memory access.
    #0 0x7f39655c2080 in llvm::Value::getContext() const (/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xac1080)
    #1 0x7f3965563c8f in llvm::StoreInst::StoreInst(llvm::Value*, llvm::Value*, bool, llvm::MaybeAlign, llvm::AtomicOrdering, unsigned char, llvm::Instruction*) (/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa62c8f)
    #2 0x7f3965563bc7 in llvm::StoreInst::StoreInst(llvm::Value*, llvm::Value*, bool, llvm::Instruction*) (/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa62bc7)
    #3 0x7ae58f in llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::CreateStore(llvm::Value*, llvm::Value*, bool) /usr/lib/llvm-10/include/llvm/IR/IRBuilder.h:1699:23
    #4 0x7a20b7 in bpftrace::ast::CodegenLLVM::createPrintNonMapCall(bpftrace::ast::Call&, int&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:2375:8
    #5 0x79d618 in bpftrace::ast::CodegenLLVM::visit(bpftrace::ast::Call&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:777:7
    #6 0x78ea90 in bpftrace::ast::Call::accept(bpftrace::ast::Visitor&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/ast.cpp:131:5
    #7 0x7a858a in bpftrace::ast::CodegenLLVM::visit(bpftrace::ast::ExprStatement&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:1489:14
    #8 0x78f9a3 in bpftrace::ast::ExprStatement::accept(bpftrace::ast::Visitor&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/ast.cpp:291:5
    #9 0x7aa0bf in bpftrace::ast::CodegenLLVM::generateProbe(bpftrace::ast::Probe&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, llvm::FunctionType*, bool) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:1776:11
    #10 0x7aa4ba in bpftrace::ast::CodegenLLVM::visit(bpftrace::ast::Probe&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:1807:5
    #11 0x790133 in bpftrace::ast::Probe::accept(bpftrace::ast::Visitor&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/ast.cpp:383:5
    #12 0x7aafab in bpftrace::ast::CodegenLLVM::visit(bpftrace::ast::Program&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:1910:12
    #13 0x7901e3 in bpftrace::ast::Program::accept(bpftrace::ast::Visitor&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/ast.cpp:392:5
    #14 0x7ad528 in bpftrace::ast::CodegenLLVM::compile(bpftrace::DebugLevel, std::ostream&) /home/ubuntu/work/bpftrace/bpftrace/src/ast/codegen_llvm.cpp:2409:10
    #15 0x710f8d in main /home/ubuntu/work/bpftrace/bpftrace/src/main.cpp:650:19
    #16 0x7f39617e1b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #17 0x4830c9 in _start (/home/ubuntu/work/bpftrace/bpftrace/build_dev/src/bpftrace+0x4830c9)

@fbs
Copy link
Contributor

fbs commented Jun 13, 2020

Looks good, the synchronous part got me a bit confused tho, I think it needs some clarification to not confuse users.
The whole thing is still async in the sense that the bpf program (likely) terminates before the event handles, all events are "queued" waiting for userspace. The difference between map and this is that with maps we send a mapid (pointer) to be printed, which means the value could have changed before the printing, while for values it sends the value.

Consulting the generated IR, it seems this is the same bug as #1332. The buffer holding the result of bpf_get_current_comm is overwritten before use. (The async id of print is 30007 = 0x7537 = 'u' and '7'.) This bug is really annoying..

Ugh this seems to bite us everywhere now. I need to get it finshed

@danobi
Copy link
Member Author

danobi commented Jun 15, 2020

Consulting the generated IR, it seems this is the same bug as #1332.

Ok, will leave that alone for now. I'll try to take a look if I get time.

$ sudo ./src/bpftrace -e 'BEGIN { print(exit()); }'
AddressSanitizer:DEADLYSIGNAL

Fixed. Forgot to exclude Type::none from printable types.

Looks good, the synchronous part got me a bit confused tho, I think it needs some clarification to not confuse users.

Updated. Now reads:

It is important to note that printing values is different than printing maps.
Both printing maps and printing values are asynchronous: the kernel queues the
event but some time later it is processed in userspace. For values, the event
contains the memcopy'd value so the value at `print()` invocation time will be
printed.  However for maps, only the handle to the map is queued up, so the
printed map may be different than the map at `print()` invocation.

@fbs
Copy link
Contributor

fbs commented Jun 22, 2020

LGTM, should we squash this or leave it as is?

@danobi
Copy link
Member Author

danobi commented Jun 29, 2020

I'll squash; commits only seem useful for code review

@danobi danobi merged commit 2a76f94 into bpftrace:master Jun 29, 2020
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.

print() for non maps
3 participants