How to parse struct data from bpf_probe_read function
- Dominant language
- C
- Stars
- 22.7k
- Forks
- 4.1k
- Avg merge
- 5d 13h
- Merged PRs (30d)
- 3
Description
I have been trying to attach uprobe to **ngx_http_process_request** function of nginx and note time taken by this function. The eBPF code looks like this:
```
#include
#include
struct val_t {
u32 pid;
char comm[TASK_COMM_LEN];
char url[80];
u64 ts;
};
struct data_t {
u32 pid;
u64 delta;
char comm[TASK_COMM_LEN];
char url[80];
};
BPF_HASH(start, u32, struct val_t);
BPF_PERF_OUTPUT(events);
int do_entry(struct pt_regs *ctx) {
if (!PT_REGS_PARM1(ctx))
return 0;
struct val_t val = {};
u32 pid = bpf_get_current_pid_tgid();
if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
bpf_probe_read(&val.url, sizeof(val.url),
(void *)PT_REGS_PARM1(ctx));
val.pid = bpf_get_current_pid_tgid();
val.ts = bpf_ktime_get_ns();
start.update(&pid, &val);
}
return 0;
}
int do_return(struct pt_regs *ctx) {
struct val_t *valp;
struct data_t data = {};
u64 delta;
u32 pid = bpf_get_current_pid_tgid();
u64 tsp = bpf_ktime_get_ns();
valp = start.lookup(&pid);
if (valp == 0)
return 0; // missed start
bpf_probe_read(&data.comm, sizeof(data.comm), valp->comm);
bpf_probe_read(&data.url, sizeof(data.url), (void *)valp->url);
data.pid = valp->pid;
data.delta = tsp - valp->ts;
events.perf_submit(ctx, &data, sizeof(data));
start.delete(&pid);
return 0;
}
```
```
bpf_probe_read(&val.url, sizeof(val.url), (void *)PT_REGS_PARM1(ctx));
```
The **bpf_probe_read** command tries to read the 1st argument of the function. I am trying to store this into a char[80] variable. This makes sense when the param is a string but as we can see in the [source code of nginx](https://github.com/nginx/nginx/blob/ecfab06cb20959219c9aadc2ef59507488e4fa99/src/http/ngx_http.h#L121), this function takes in `ngx_http_request_t` type as input argument which itself is defined as
`typedef struct ngx_http_request_s ngx_http_request_t;`
and the `ngx_http_request_s` is defined at [Link](https://github.com/nginx/nginx/blob/27b3d3dcca5fcc82350a823881f3d06161327b59/src/http/ngx_http_request.h#L371) and this struct has **uri, method,** etc as fields. I want to access those fields in my code and print them.
It currently prints **HTTP** as the 1st argument of function which is defined as signature int field at [Line 372 ](https://github.com/nginx/nginx/blob/27b3d3dcca5fcc82350a823881f3d06161327b59/src/http/ngx_http_request.h#L372) of code.
Most of the examples of eBPF show only string or int as function argument. I want to understand how to parse struct data as function argument.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with nginx/src/http/ngx_http.h at ngx_http_process_request and nginx/src/http/ngx_http_request.h at ngx_http_request_s, then compare those fields with the uprobe entry and return handlers shown in the issue. Verify how the request pointer and its nested fields are represented before deciding what a usable BCC example should demonstrate; done means the struct fields can be read and reported correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, linux, nginx
- Domain
- observability-sre
- Issue type
- Documentation
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100