RFR: 8369994: Mixed mode jhsdb jstack cannot resolve symbol with cold attribute
Kevin Walls
kevinw at openjdk.org
Sun Oct 19 20:05:01 UTC 2025
On Thu, 16 Oct 2025 13:32:28 GMT, Yasumasa Suenaga <ysuenaga at openjdk.org> wrote:
> `jhsdb jstack --mixed` with coredump cannot resolve function symbol which has `.cold` attribute.
>
>
> ----------------- 120485 -----------------
> "Thread-0" #24 prio=5 tid=0x00007f50dc1aa7c0 nid=120485 waiting on condition [0x00007f50c0d1a000]
> java.lang.Thread.State: TIMED_WAITING (sleeping)
> JavaThread state: _thread_blocked
> 0x00007f50e4710735 __GI_abort + 0x8b
> 0x00007f50e1e01f33 ????????
>
>
> 0x7f50e1e01f33 was `os::abort(bool, void const*, void const*) [clone .cold]` and I could see it in GDB. However it has `.cold` suffix, it means the code has been relocated as ["cold" function](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-cold-function-attribute). In GDB, we can see the code in another area from function body as following:
>
>
> (gdb) disas 0x7f50e1e01f2e, 0x7f50e1e01f34
> Dump of assembler code from 0x7f50e1e01f2e to 0x7f50e1e01f34:
> 0x00007f50e1e01f2e <_ZN2os5abortEbPKvS1_.cold+0>: call 0x7f50e1e01010 <abort at plt>
> => 0x00007f50e1e01f33: nop
> End of assembler dump.
>
>
> libsaproc.so checks address range to resolve symbol whether the address is in between `start` and `start + size - 1`. As you can see in assembler dump, the code in `.cold` section is `call` instruction, thus IP points next `nop`, thus we should allow address range between `start` and `start + size`.
>
> After this PR, you can see the right symbol as following:
>
>
> ----------------- 120485 -----------------
> "Thread-0" #24 prio=5 tid=0x00007f50dc1aa7c0 nid=120485 waiting on condition [0x00007f50c0d1a000]
> java.lang.Thread.State: TIMED_WAITING (sleeping)
> JavaThread state: _thread_blocked
> 0x00007f50e4710735 __GI_abort + 0x8b
> 0x00007f50e1e01f33 os::abort(bool, void const*, void const*) [clone .cold] + 0x5
Are you thinking of doing a second pass: if symbol not found, look again using RIP-1. That should work for this case.
(Or on the second pass, use the one byte longer object/function length.)
It won't be perfect but I'm not sure what will be without getting quite context sensitive. Even recognising that we are looking one byte past the end of a function, and that the instruction immediately lower in memory was a call, would need checking whether the called frame is that call, or if we just jumped to a function that starts in memory immediately after a funtion that ends in a call.
I think we should be OK with something that works for most cases, and works better than today, and maybe the second pass does that. 8-)
-------------
PR Comment: https://git.openjdk.org/jdk/pull/27846#issuecomment-3419917455
More information about the serviceability-dev
mailing list