ostash / perfgrind

perfgrind - tools for collecting samples from Linux performance events subsystem and converting profiling data to callgrind format, allowing it to be read with KCachegrind
Other
13 stars 2 forks source link

PIE not handled properly in pgconvert #25

Closed GitMensch closed 9 months ago

GitMensch commented 10 months ago

I've just cloned the repo and run make check which worked fine, then make open-checkfiles.

cc -std=gnu99  -O2 -Wall -Wextra -g  -D_GNU_SOURCE -o pgcollect  pgcollect.c
g++ -std=c++03 -O2 -Wall -Wextra -g  -o pgconvert  pgconvert.cpp AddressResolver.cpp Profile.cpp -ldw -lelf
g++ -std=c++03 -O2 -Wall -Wextra -g  -o pginfo     pginfo.cpp    AddressResolver.cpp Profile.cpp -ldw -lelf
g++ -std=c++03 -O  -Wall -Wextra -g  -g -fno-omit-frame-pointer -o pginfo_dbg pginfo.cpp    AddressResolver.cpp Profile.cpp -ldw -lelf

collecting some data of ls binary (likely without full symbols)...
./pgcollect check_ls.pgdata -F 2048 -s -- ls -l /usr/bin  1>/dev/null

collecting data of checking that (guaranteed to have symbols for binary pginfo_dbg) ...
./pgcollect check.pgdata    -F 2048 -s -- ./pginfo_dbg callgraph check_ls.pgdata
Setting frequency to 2048
Going to profile process with PID 30725: ./pginfo_dbg callgraph check_ls.pgdata
memory objects: 3
entries: 19

mmap events: 19
good sample events: 15
bad sample events: 0
total sample events: 15
total events: 34
Collection stopped.
Waked up 1 times
Sythetic mmap events: 0
Real mmap events: 43
Sample events: 6
Total 49 events written

checking its infos ...
./pginfo callgraph check.pgdata
memory objects: 5
entries: 14

mmap events: 43
good sample events: 6
bad sample events: 0
total sample events: 6
total events: 49

converting both collections to callgrind format ...
./pgconvert check_ls.pgdata -d object       1> check_ls.grind  # old: stdout
Can't resolve symbol for address 154a1, load base: 55f323480000
Can't resolve symbol for address 15d300, load base: 7feffd84a000
./pgconvert check.pgdata    -d source -i       check.grind     # new: second option

The result looks reasonable so far but opening on KCachegrind shows nearly an empty source and most checking of machine code prompts an error, which is rooted in the objdump calls that use the address from the profile - and those don't exist in the binary.

If I run those manually I get.

objdump -C -d --start-address=0x2F1E --stop-address=0x2F46 /home/build/perfgrind/pginfo_dbg

/home/build/perfgrind/pginfo_dbg:     file format elf64-x86-64

run without the address:

 objdump -C -d  /home/build/perfgrind/pginfo_dbg | head -n 20

/home/build/perfgrind/pginfo_dbg:     file format elf64-x86-64

Disassembly of section .init:

0000000000003000 <_init>:
    3000:       48 83 ec 08             sub    $0x8,%rsp
    3004:       48 8b 05 dd 8f 00 00    mov    0x8fdd(%rip),%rax        # bfe8 <__gmon_start__>
    300b:       48 85 c0                test   %rax,%rax
    300e:       74 02                   je     3012 <_init+0x12>
    3010:       ff d0                   callq  *%rax
    3012:       48 83 c4 08             add    $0x8,%rsp
    3016:       c3                      retq

Disassembly of section .plt:

0000000000003020 <.plt>:
    3020:       ff 35 e2 8f 00 00       pushq  0x8fe2(%rip)        # c008 <_GLOBAL_OFFSET_TABLE_+0x8>
    3026:       ff 25 e4 8f 00 00       jmpq   *0x8fe4(%rip)        # c010 <_GLOBAL_OFFSET_TABLE_+0x10

Any idea what's going on here?

ostash commented 10 months ago

Did you profile contains any hits to the executable binary itself? I've got only hits to libc.so and ld-linux.so, but after increasing frequency and disabling software events managed to get hit to the executable itself.

I'm afraid the workload we're profiling is just too small to collect any meaningful data.

GitMensch commented 10 months ago

Did you profile contains any hits to the executable binary itself?

Yes, but not when I retried that.

I've got only hits to libc.so and ld-linux.so, but after increasing frequency and disabling software events managed to get hit to the executable itself.

Seen that on re-testing. But even with a higher frequency and no software event and binaries in the profile I'm back to the original problem: objdump is called with address that doesn't exist because pgconvert put that into the cachegrind profile. Do you see the same?

ostash commented 9 months ago

Nope, everything looks to be working fine for me. Can you provide me with your binary, pgdata and grind files?

GitMensch commented 9 months ago

Sure. check.zip

ostash commented 9 months ago

Well, looks to be working fine for me:

image

GitMensch commented 9 months ago

Does that include the machine code for all functions in pginfo_dbg? This is where the error is we track under this issue is most visible.

ostash commented 9 months ago

Ok, got it finally. Your executable is PIE, this is not handled properly in pgconvert.

GitMensch commented 9 months ago

Is this issue likely to stay open or can you have a look at this in the next weeks? In the former case we should update the README, possibly linking this issue to document this regression.

ostash commented 9 months ago

This should be fixable :)

ostash commented 9 months ago

Ok, I was wrong: non-PIE executables have wrong instructions dump as well.

ostash commented 9 months ago

Should be fixed by 0a8fd1c819973204093fd980d609e997735763f7, please test.

GitMensch commented 9 months ago

I didn't checked that specific commit but do so that current master fixed that.