I have a simple C++ program with the function fibonacci, where I want to attach a uprobe.
With normal linking, this works finde. But with static linking, I get an error attaching to the new adress.
My machine:
- Raspbian 5.15.45, arm aarch64 Raspberry Pi 4
- The function I want to attach to is called "fibonacci", just a normal C++ function in a simple program.
Dynamic linking:
With objdump --syms fibonacci I get the address 0x3b03c:
000000000003b03c g F .text 0000000000000062 _Z9fibonaccim
So I tell the bpf loader to attach the uprobe to 0x3b03c.
This works fine.
For building, I use CMAKE:
list(APPEND SOURCES main.cc)
add_executable(fibonacci ${SOURCES})
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/[...]/json/include/")
target_include_directories(fibonacci PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # Disable optimization
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
install(TARGETS fibonacci DESTINATION "${PROJECT_BUILD_DIR}/")
VERBOSE=1 make yields
/bin/x86_64-linux-gnu-g++-9 -I/home/[...]/build -I/home/[...]/json/include -g -O0 -std=gnu++17 -o CMakeFiles/fibonacci.dir/main.cc.o -c /home/[...]/main.cc
/bin/x86_64-linux-gnu-g++-9 -g -O0 -rdynamic CMakeFiles/fibonacci.dir/main.cc.o -o fibonacci
Problems raise if I add the line target_link_libraries(fibonacci -static) to the CMakeLists.txt.
VERBOSE=1 make yields
/bin/x86_64-linux-gnu-g++-9 -I/home/[...]/build -I/home/[...]/json/include -g -O0 -std=gnu++17 -o CMakeFiles/fibonacci.dir/main.cc.o -c /home/[...]/main.cc
/bin/x86_64-linux-gnu-g++-9 -g -O0 -rdynamic CMakeFiles/fibonacci.dir/main.cc.o -o fibonacci -static
The only difference is the -static for linking.
objdump --syms fibonacci shows that the address changed to 0x401424:
0000000000401424 g F .text 0000000000000062 _Z9fibonaccim
Now, attaching the bpf program to the new address does not work anymore. I get the following output:
libbpf: loading [...]uprobe_fibonacci_0x401424.bpf.o
libbpf: elf: section(3) kprobe/xxx, size 200, link 0, flags 6, type=1
libbpf: sec 'kprobe/xxx': found program 'main_entry' at insn offset 0 (0 bytes), code size 25 insns (200 bytes)
libbpf: elf: section(4) .relkprobe/xxx, size 16, link 21, flags 0, type=9
libbpf: elf: section(5) license, size 4, link 0, flags 3, type=1
libbpf: license of [...]uprobe_fibonacci_0x401424.bpf.o is GPL
libbpf: elf: section(6) .maps, size 32, link 0, flags 3, type=1
libbpf: elf: section(13) .BTF, size 1666, link 0, flags 0, type=1
libbpf: elf: section(15) .BTF.ext, size 268, link 0, flags 0, type=1
libbpf: elf: section(21) .symtab, size 1512, link 1, flags 0, type=2
libbpf: looking for externs among 63 symbols...
libbpf: collected 0 externs total
libbpf: map 'runtimeSimpleCtx_storage_0': at sec_idx 6, offset 0.
libbpf: map 'runtimeSimpleCtx_storage_0': found type = 2.
libbpf: map 'runtimeSimpleCtx_storage_0': found key [2], sz = 4.
libbpf: map 'runtimeSimpleCtx_storage_0': found value [7], sz = 16.
libbpf: map 'runtimeSimpleCtx_storage_0': found max_entries = 1.
libbpf: sec '.relkprobe/xxx': collecting relocation for section(3) 'kprobe/xxx'
libbpf: sec '.relkprobe/xxx': relo #0: insn #19 against 'runtimeSimpleCtx_storage_0'
libbpf: prog 'main_entry': found map 0 (runtimeSimpleCtx_storage_0, sec 6, off 0) for insn #19
err from bpf_object__open_file: Success (0)
Getting programs
err from prog: Success (0)
Checking maps
- Found map runtimeSimpleCtx_storage_0
Done loading bpf object file.
libbpf: map 'runtimeSimpleCtx_storage_0': created successfully, fd=4
libbpf: sec 'kprobe/xxx': found 1 CO-RE relocations
libbpf: CO-RE relocating [19] struct user_pt_regs: found target candidate [200] struct user_pt_regs in [vmlinux]
libbpf: prog 'main_entry': relo #0: <byte_off> [19] struct user_pt_regs.regs[0] (0:0:0 @ offset 0)
libbpf: prog 'main_entry': relo #0: matching candidate #0 <byte_off> [200] struct user_pt_regs.regs[0] (0:0:0 @ offset 0)
libbpf: prog 'main_entry': relo #0: patched insn #3 (ALU/ALU64) imm 0 -> 0
Object load: Success (0)
Attaching uprobe uprobe_fibonacci_0x401424.bpf.o to fibonacci/0x401424
- PID: 5026
- Address: 0x401424
libbpf: uprobe perf_event_open() failed: Invalid argument
libbpf: prog 'main_entry': failed to create uprobe '/proc/5026/exe:0x401424' perf event: Invalid argument
- ERROR: Invalid argument (-22)
I wrote a loop to try all the addresses:
cout << "hacky test" << endl;
for(uint64_t i = address; i != 0; --i)
{
link = bpf_program__attach_uprobe_opts( prog,
pid /* pid */,
execPath.c_str(),
i,
&opts);
if(libbpf_get_error(link) != 0)
{
cout << i << ": " << bpfGetError(link) << endl;
}
else
{
cout << i << ": SUCCESS!: " << bpfGetError(link) << endl;
break;
}
}
This leads to the output
2625179: Invalid argument (-22)
libbpf: uprobe perf_event_open() failed: Invalid argument
libbpf: prog 'main_entry': failed to create uretprobe '/proc/5026/exe:0x280e9a' perf event: Invalid argument
2625178: Invalid argument (-22)
libbpf: uprobe perf_event_open() failed: Invalid argument
libbpf: prog 'main_entry': failed to create uretprobe '/proc/5026/exe:0x280e99' perf event: Invalid argument
2625177: Invalid argument (-22)
2625176: SUCCESS!: Success (0)
The addresses do not look like any pattern to me:
- 4199460 = 0h401424 = 0b010000000001010000100100 - ERROR
- 2625177 = 0h280E99 = 0b001010000000111010011001 - ERROR
- 2625176 = 0h280E98 = 0b001010000000111010011000 - OK
Attaching to the pid with gdb shows that the function fibonacci is at the expected address 0x401424, whereas gdb cannot read the memory on location 0x280e9a or 0x280e99.
Therefore, I can attach uprobes to random looking addresses where there should not be anything, but not to the address of my function.
The pid (5026) is correct (checked in htop).
Does somebody have any idea what could be wrong? Thanks in advance!