We saw what a uProbe-type program was in part one: a way to probe the functions of your programs.
In this part, we will first create a very simple program in Go and make it interact with two eBPF programs:
- The first is a uProbe type
- The second is a uRetProbe type
I assume you are already in an environment for developing with Aya and that you have installed the go compiler and bpftrace. If not, you can use the Killercoda lab:
Let’s create a program to test the uProbes#
A very simple code#
For a change from Rust, we’re going to create a small program in Go:
// hello.go
package main
import "fmt"
func hello() int {
fmt.Println("Hello, world!")
return 3
}
func main() {
ret := hello()
fmt.Println("Returned:", ret)
}
How do we activate uProbes?#
The purpose of this article is to activate:
- an eBPF program of type uProbe each time we enter the
hello()
function:
- an eBPF program of type uRetProbe each time we exit the
hello()
function:
Now that we have seen the ins and outs of the article, let’s move on to compiling the program.
Let’s compile the program#
To compile it, just type:
go build -gcflags="all=-N -l" -o hello hello.go
You may notice that we added an option -gcflags="all=-N -l"
. Normally, you don’t need to use this option to compile a Go program:
go build -o hello hello.go
This also works. So why use this option?
-gcflags
means go compiler flags; these are options passed to the Go compiler.all
means that the options apply to all compiled packages.
The options specified to the Go compiler are:
-N
: by default, the compiler modifies (mangles) the function name. This option disables this modification.
-l
: by default, the compiler inlines functions, i.e., it directly integrates the content of the function into the calling code, thus allowing programs to perform better. This option allows you to disable this inline.
These options will allow us to keep the functions and make them readable, which will make it easier for us to find the attachment point for our eBPF program.
How to find the attachment point?#
Now that we have created and compiled the small program, we need to figure out how to trigger the uProbe or uRetProbe type eBPF program. When using cargo generate
for the aya repo, we need to answer two questions: where is the binary name and which function is being observed. Let’s take a closer look.
Name of the binary#
🤷 Target to attach the (u|uret)probe? (e.g libc):
To ensure the portability of the eBPF program, you must answer with the absolute path of the binary. For example, I created it here: /home/cloud_user/hello
.
Function name#
Once you have answered the first question, there is a second question:
🤷 Function name to attach the (u|uret)probe? (e.g getaddrinfo):
What should you answer? You might be tempted to answer hello
since you set the -N
option, which disables name decoration during compilation.
But it’s a little more complicated than that. The Go compiler still slightly modifies the function name during the compilation stage.
As we saw in the previous episode, to find all the functions in a binary, just use bpftrace
:
bpftrace -l 'uprobe:/home/cloud_user/hello:*'
- The
-l
option lists all available probes uprobe
: the type of eBPF program/home/cloud_user/hello
: the location of the binary*
: the wildcard (0 or more characters)
The display format is then:
uprobe:/home/cloud_user/hello:[function1]
uprobe:/home/cloud_user/hello:[function2]
uprobe:/home/cloud_user/hello:[function3]
uprobe:/home/cloud_user/hello:[function4]
etc
That’s unfortunate: the function name is the same as my file name… We can’t do | grep hello
. How can we get around this? With awk
, cut
, or worse, a regex?
Let’s keep it simple:
bpftrace -l 'uprobe:/home/cloud_user/hello:*hello*'
And it will respond with:
uprobe:/home/cloud_user/hello:main.hello
So the real name of the function is main.hello
nm
command. It allows you to see all the symbols that are present in a binary file.Now that we have the answers to both questions, we can create our eBPF programs.
Let’s start with the uProbe-type program.
Let’s create an eBPF uProbe program#
Let’s test with bpftrace#
Continued reading reserved for premium members ✨
The full article is only available to premium members.
Becoming a premium member is easy: just make a small donation 💖
In exchange, you will receive for 1 year (early bird offer):
- Access to all full articles as soon as they are published
- Early reading before public release
- Participation in supporting this independent blog
- Exclusive access to my vacation photos in Dubai
Your donation will help:
- Make me less dependent on large platforms
- Encourage me to create more technical content
- Lift the paywall more quickly for everyone