0x1000 offset in symbol resolution?

Milian Wolff mail@milianw.de
Wed Dec 30 15:51:01 GMT 2020


Hey all,

I stumbled upon a strange behavior while symbolizing a perf.data file with 
hotspot/perfparser/elfutils that I have trouble understanding. I hope it's ok 
to send this call for help here.

I'm running with elfutils 0.181, g++ 10.2, glibc 2.32 on archlinux with kernel 
5.9.14.

Code for the executable:
https://github.com/KDAB/hotspot/blob/master/tests/test-clients/cpp-inlining/
main.cpp

Then compile it and run with perf:

```
$ g++ -O2 -g main.cpp
$ perf record ./a.out
$ perf script --show-mmap-events | grep -E 'main|MMAP' | head
           a.out 108684 15892.199058: PERF_RECORD_MMAP2 108684/108684: 
[0x561875084000(0x1000) @ 0 fe:00 7997193 372428903]: r-xp /home/milian/
projects/kdab/rnd/hotspot/build/a.out
...
           a.out 108684 15892.200561:     391517 cycles:u:      561875084c1e 
main+0x1de (/home/milian/projects/kdab/rnd/hotspot/build/a.out)
```

The first MMAP event show us that there's a mapping starting at 0x561875084000 
with a size of 0x1000 that belongs to the main executable, pgoff is 0.

Later on, we see e.g. the instruction pointer address 0x561875084c1e being 
somehow mapped to main+0x1de by perf using the binutils libraries.

What's odd is that this should give us the offset of main:

```
0x561875084c1e - 0x561875084000 = 0xc1e
0xc1e - 0x1de = 0xa40
```

But look at what we get from nm:

```
$ eu-nm ./a.out | grep main
main                                                                         |
0000000000001a40|GLOBAL|FUNC    |00000000000002e5|main.cpp:33|.text
```

Note that the address in the symbol table is actually 0x1000 offset from the 
0xa40 value we computed above... Can anyone explain that?

GDB shows a similar behavior:

```
$ gdb a.out
(gdb) b main
Breakpoint 1 at 0x1a40: file ../tests/test-clients/cpp-inlining/main.cpp, line 
34.
(gdb) r
Starting program: /home/milian/projects/kdab/rnd/hotspot/build/a.out 

Breakpoint 1, main () at ../tests/test-clients/cpp-inlining/main.cpp:34
34      {
(gdb) p/x $rip
$1 = 0x555555555a40
(gdb) p/x &main
$2 = 0x555555555a40
(gdb) info proc mappings 
process 109516
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
      0x555555554000     0x555555555000     0x1000        0x0 /home/milian/
projects/kdab/rnd/hotspot/build/a.out
      0x555555555000     0x555555556000     0x1000        0x0 /home/milian/
projects/kdab/rnd/hotspot/build/a.out
      0x555555556000     0x555555558000     0x2000        0x0 /home/milian/
projects/kdab/rnd/hotspot/build/a.out
      0x555555558000     0x555555559000     0x1000     0x1000 /home/milian/
projects/kdab/rnd/hotspot/build/a.out
...
(gdb) 
```

So here, the address `0x555555555a40` should come from the second mapping, 
which has an offset 0x0 and starts at `0x555555555000` and has a size of 
`0x1000`. How can that possibly map to the `main` symbol which has an offset 
of `0x1a40`?

Does anyone know what's going on here?

Thanks

-- 
Milian Wolff
mail@milianw.de
http://milianw.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <https://sourceware.org/pipermail/elfutils-devel/attachments/20201230/9b32747e/attachment.sig>


More information about the Elfutils-devel mailing list