Closed 64J0 closed 1 year ago
~Everything looks in order here. The eBPF backend in LLVM is evolving, and different versions of clang may generate slightly different versions of the eBPF bytecode for a given program - this is nothing unexpected.~
~If you're really curious about it, you could try different versions of clang, or even compile it to bisect and pin down what change in the LLVM repo caused the difference in the bytecode :).~
Scratch the above, I didn't read correctly and replied too fast, sorry.
One thing that was valid from my previous comment: Everything is still in order :), you've done nothing wrong here.
So your loaded program has two more instructions (46, given numbering starts from 0) than the initial bytecode. Let's compare the instructions from the program you load with what's in the kernel. We can make BCC print the raw bytecode:
iff --git a/chapter4/hello-buffer-config.py b/chapter4/hello-buffer-config.py
index 59c9fd131a68..7f0fb2abcd31 100755
--- a/chapter4/hello-buffer-config.py
+++ b/chapter4/hello-buffer-config.py
@@ -45,6 +45,8 @@ int hello(void *ctx) {
b = BPF(text=program)
syscall = b.get_syscall_fnname("execve")
b.attach_kprobe(event=syscall, fn_name="hello")
+print(b.dump_func("hello").hex())
+exit()
b["config"][ct.c_int(0)] = ct.create_string_buffer(b"Hey root!")
b["config"][ct.c_int(501)] = ct.create_string_buffer(b"Hi user 501!"
Run it:
# ./hello-buffer-config.py | fold -w 16
bf16000000000000
b701000000000000
631af8ff00000000
7b1af0ff00000000
7b1ae8ff00000000
7b1ae0ff00000000
b7010000726c6400
631ad0ff00000000
1801000048656c6c
000000006f20576f
7b1ac8ff00000000
850000000e000000
7700000020000000
630ad8ff00000000
850000000f000000
630adcff00000000
bfa1000000000000
07010000e0ffffff
b702000010000000
8500000010000000
1811000005000000
0000000000000000
bfa2000000000000
07020000dcffffff
8500000001000000
<2 missing instructions here, number 25 and 26 from your output>
bfa3000000000000
07030000c8ffffff
1500010000000000
bf03000000000000
bfa1000000000000
07010000f0ffffff
b70200000c000000
8500000071000000
1812000004000000
0000000000000000
bfa4000000000000
07040000d8ffffff
bf61000000000000
18030000ffffffff
0000000000000000
b705000024000000
8500000019000000
b700000000000000
9500000000000000
(I added the note on missing instructions to this output, obviously.)
So the kernel adds two instructions after your map lookup:
24: (85) call __htab_map_lookup_elem#181488
25: (15) if r0 == 0x0 goto pc+1
26: (07) r0 += 56
Where do these instructions come from? Note how __htab_map_lookup_elem
has replaced bpf_map_lookup_elem
. This is a hint: the verifier has inlined the map lookup. As explained in the comments for the relevant function, this means that it replaces the following call sequence:
* bpf_prog
* bpf_map_lookup_elem
* map->ops->map_lookup_elem
* htab_map_lookup_elem
* __htab_map_lookup_elem
with the following, less costly at runtime:
* bpf_prog
* __htab_map_lookup_elem
But to do that, it must add a few additional instructions, that would otherwise be called from the function we're now skipping. That's where you get the additional check from.
Great, thanks for the detailed answer @qmonnet! Now it's clearer to me.
Description:
Hello, hope you're good.
When I was working in the 1st exercise of the 4th chapter, I noticed that the values are different.
So, my thought process was:
First, use the command specified in the chapter:
Notice that the
insn_cnt
value is 44.Then, for checking the number of instructions from the dumped eBPF program I used:
As I'm understanding it, the result is 45, which is different than 44.
Am I doing something wrong in this case?