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

runtime: ebpf uprobe support #22008

Open
shashankmjain opened this issue Sep 25, 2017 · 8 comments

Comments

@shashankmjain
Copy link

@shashankmjain shashankmjain commented Sep 25, 2017

We had issue with using uprobes with ebpf due to dynamic nature of golang stacks. Is there a proposal/way to address that?

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Sep 25, 2017

What is ebpf? What are uprobes?

The Go compiler is committed to having stacks that grow, and therefore move, as needed. That is a key part of supporting programs that use a very large number of goroutines.

@shashankmjain

This comment has been minimized.

Copy link
Author

@shashankmjain shashankmjain commented Sep 25, 2017

ebpf is the linux tracing mechanism and uprobes are dynamic probes for user space programs. The ebpf program attaches to a user probe and gets executed when that function is invoked. Here it seems the golang stack is resized and the return of the ebpf program gets a segmentation fault as it points to a invalid address

@cznic

This comment has been minimized.

Copy link
Contributor

@cznic cznic commented Sep 25, 2017

Sounds like ebpf/uprobes supports only processes having a pure C ABI with thread-static stacks .

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Sep 25, 2017

I don't see how we could support a dynamic probe executed by the kernel that refers to a local address on the stack.

@ianlancetaylor ianlancetaylor changed the title ebpf uprobe support runtime: ebpf uprobe support Sep 25, 2017
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Sep 25, 2017
@brendangregg

This comment has been minimized.

Copy link

@brendangregg brendangregg commented Sep 25, 2017

Anyway for go to pause the moving of stacks, eg, by sending it a signal? That way the behavior could be disabled temporarily while the kernel did user-level instrumentation.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Sep 25, 2017

The SIGSTOP signal would work.

There is no way to disable moving stacks other than stopping the program, though. There can't be: program execution could require additional stack space at any time.

@gianlucaborello

This comment has been minimized.

Copy link

@gianlucaborello gianlucaborello commented Jul 25, 2018

FYI I posted a tentative solution that I'm experimenting with to work around this problem, and would appreciate comments and skepticisms: iovisor/bcc#1320 (comment)

Thanks

@Lekensteyn

This comment has been minimized.

Copy link
Contributor

@Lekensteyn Lekensteyn commented Aug 20, 2019

The title and description is misleading. Uprobes do in fact work with Go programs. What does not work are uretprobes.

A uprobe is associated with a userspace program binary and offset. When a probe is added, Linux will load that program, save the old instruction at the absolute file offset and patch it with a trap instruction. When the probe is hit, the eBPF program will be executed in kernel space. This works fine with normal uprobes.

A uretprobe patches a function in a similar way at entry, but it will modify the return address on the stack to a trampoline function. Once hit, the EBPF program is executed and the instruction pointer is modified to the original return address again. If the stack changes, this will likely cause corruption and crashes.

uretprobes should not be used with Go programs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.