Repository navigation
Commit 2edcadb
committed
Emit nop1,nop5 instructions for x86_64 usdt probe
We can currently optimize uprobes on top of nop5 instructions,
so application can define USDT_NOP to nop5 and use USDT macro
to define optimized usdt probes.
This works fine on new kernels, but could have performance penalty
on older kernels. Until Linux vX.Y kernel's uprobe implementation
treated nop5 as an instruction that needs to be single-stepped.
execution of the usdt probe on top of nop1 on old kernels:
- nop1 -> trigger usdt -> emulate nop1 -> continue
execution of the usdt probe on top of nop5 on old kernels:
- nop5 -> trigger usdt -> single step nop5 -> continue
Note the 'single step nop5' as the source of performance regression.
This creates a dilemma where we want nop5 on new kernels and nop1
on old ones, but we can't know upfront which kernel we'll run on.
To workaround that we change the USDT macro to emit nop1,nop5 for
the probe (instead of default nop1) and make record of that in
USDT record (more on that below).
This can be detected by application (libbpf) and it can place the
uprobe either on nop1 or nop5 based on the optimization support in
the kernel.
We make record of using the nop1,nop5 instructions in the USDT ELF
note data.
Current elf note format is as follows:
namesz (4B) | descsz (4B) | type (4B) | name | desc
And current usdt record (with "stapsdt" name) placed in the note's
desc data look like:
loc_addr | 8 bytes
base_addr | 8 bytes
sema_addr | 8 bytes
provider | zero terminated string
name | zero terminated string
args | zero terminated string
None of the tested parsers (bpftrace-bcc, libbpf) checked that the args
zero terminated byte is the actual end of the 'desc' data. As Andrii
suggested we could use this and place extra zero byte right there as an
indication for the parser we use the nop1,nop5 instructions.
It's bit tricky, but the other way would be to introduce new elf note type
or note name and change all existing parsers to recognize it. With the change
above the existing parsers would still recognize such usdt probes and use
safer (performance-wise) nop1 as uprobe target
We can treat this extra zero as a backwards-compatible extension of
provider+name+args section. If we ever need to have some extra flags
or extra information (e.g., argument names or whatnot), we can treat
this as either a fourth string or think about this as a single-byte
length prefix for a fixed binary extra information that should follow
(right now it's zero, so forward-compatible). For now just extra zero
is the least amount of work but good enough to solve the problem,
while being extendable for the future.
Note we do not emit this extra byte if app defined its own nop through
USDT_NOP macro.
Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>1 parent f4ea2f5 commit 2edcadb
1 file changed
Lines changed: 19 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
312 | 312 | | |
313 | 313 | | |
314 | 314 | | |
| 315 | + | |
| 316 | + | |
315 | 317 | | |
316 | 318 | | |
317 | 319 | | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
318 | 328 | | |
319 | 329 | | |
320 | 330 | | |
| |||
403 | 413 | | |
404 | 414 | | |
405 | 415 | | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
406 | 424 | | |
407 | 425 | | |
408 | 426 | | |
| |||
420 | 438 | | |
421 | 439 | | |
422 | 440 | | |
| 441 | + | |
423 | 442 | | |
424 | 443 | | |
425 | 444 | | |
| |||
0 commit comments