Here is a very simple example of using BCC to trace a program and get the data from the function's argument.
A Simple Test Code in C: "test.c"
#include <stdio.h>
// student structure
struct student {
char id[15];
char firstname[64];
char lastname[64];
float points;
};
// function declaration
void getDetail(struct student *);
void displayDetail(struct student *);
int main(void) {
// student structure variable
struct student std[1];
// get student detail
getDetail(std);
// display student detail
displayDetail(std);
return 0;
}
// function definition
void getDetail(struct student *ptr) {
int i;
for (i = 0; i < 1; i++) {
printf("Enter detail of student #%d\n", (i + 1));
printf("Enter ID: ");
scanf("%s", ptr->id);
printf("Enter first name: ");
scanf("%s", ptr->firstname);
printf("Enter last name: ");
scanf("%s", ptr->lastname);
printf("Enter Points: ");
scanf("%f", &ptr->points);
// update pointer to point at next element
// of the array std
ptr++;
}
}
void displayDetail(struct student *ptr) {
int i;
for (i = 0; i < 1; i++) {
printf("\nDetail of student #%d\n", (i + 1));
// display result via ptr variable
printf("\nResult via ptr\n");
printf("ID: %s\n", ptr->id);
printf("First Name: %s\n", ptr->firstname);
printf("Last Name: %s\n", ptr->lastname);
printf("Points: %f\n", ptr->points);
// update pointer to point at next element
// of the array std
ptr++;
}
}
The simple BCC example code: "mytrace.py"
It will get and print out the string of firstname when it runs
from __future__ import print_function
from bcc import BPF
from time import strftime
import argparse
# load BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
struct str_t {
u64 pid;
char str[80];
};
// student structure
struct student {
char id[15];
char firstname[64];
char lastname[64];
float points;
};
BPF_PERF_OUTPUT(events);
int printret(struct pt_regs *ctx) {
struct str_t data = {};
char comm[TASK_COMM_LEN] = {};
u32 pid;
if (!PT_REGS_RC(ctx))
return 0;
pid = bpf_get_current_pid_tgid();
data.pid = pid;
bpf_probe_read(&data.str, sizeof(data.str),
((struct student *)PT_REGS_RC(ctx))->firstname);
bpf_get_current_comm(&comm, sizeof(comm));
events.perf_submit(ctx,&data,sizeof(data));
return 0;
};
"""
b = BPF(text=bpf_text)
b.attach_uprobe(name="<...your test binary file location...>/test",
sym="displayDetail", fn_name="printret")
# header
print("%-9s %-6s %s" % ("TIME", "PID", "ARGUMENT"))
def print_event(cpu, data, size):
event = b["events"].event(data)
print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid,
event.str.decode('utf-8', 'replace')))
b["events"].open_perf_buffer(print_event)
while 1:
try:
b.perf_buffer_poll()
except KeyboardInterrupt:
exit()
Here is the steps:
$ sudo python mytrace.py
# open another terminal
$ gcc -o test test.c
$ ./test
Enter detail of student #1
Enter ID: 1234
Enter first name: Danny
Enter last name: Liu
Enter Points: 100
Detail of student #1
Result via ptr
ID: 1234
First Name: Danny
Last Name: Liu
Points: 100.000000
Then you will see the tracing message in your previous terminal as follows:
(print out the first name from function's argument)
$ sudo python mytrace.py
TIME PID ARGUMENT
17:01:32 7265 Danny