* Re: GDB-JIT: why would my 'unwind' not be invoked on crash?
2025-11-11 21:43 GDB-JIT: why would my 'unwind' not be invoked on crash? K via Gdb
@ 2025-11-11 21:26 ` Tom Tromey
2025-11-12 2:00 ` K via Gdb
0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2025-11-11 21:26 UTC (permalink / raw)
To: K via Gdb; +Cc: K
>>>>> K via Gdb <gdb@sourceware.org> writes:
> I implemented this for the x86-64 build of my ocaml program and it works
> fine.
> I'm now working on a aarch64 version - the symtable/line and serde code is
> the same, and I'm looking to complete the unwind functionality by
> disovering how to obtain the PC (not in a general register). However, after
> arranging for a segfault
> the unwind function is not being invoked at first and I get 2 backtrace
> listings
> with appropriate function name and line numbers, and only then does gdb
> decide to call my unwind function and it does so with garbage data.
> This is understandable to the extent gdb doesn't know the ocaml stack usage.
> But if that's true, why would it proceed to generate 2 lines of backtrace
> before
> consulting my unwinder to gather the correct data?
> My expectation is it would consult my unwinder immediately.
Could you say more about what exactly you're doing?
Like are you writing an unwinder in gdb? Or writing one in Python?
If so, what prompted this as opposed to using the existing unwinders?
Like, does your compiler not generate DWARF unwind information? (If not
why not, etc.)
Anyway, there's no easy way to answer your question. Unwinding in gdb
is complicated. You could try to enable frame debugging ("set debug
frame 1") and see it says anything interesting. I think it at least
mentions which unwinders it tries.
Personally I guess if I was in your spot, I'd end up debugging the
unwinding code in gdb. If I had to guess, your unwinder is ending up
after one of the built-in ones, and one of those thinks it knows how to
unwind the frame... which could even be kind of true, one of the
difficulties in writing one is knowing when it ought to give up.
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread
* GDB-JIT: why would my 'unwind' not be invoked on crash?
@ 2025-11-11 21:43 K via Gdb
2025-11-11 21:26 ` Tom Tromey
0 siblings, 1 reply; 5+ messages in thread
From: K via Gdb @ 2025-11-11 21:43 UTC (permalink / raw)
To: gdb
I implemented this for the x86-64 build of my ocaml program and it works
fine.
I'm now working on a aarch64 version - the symtable/line and serde code is
the same, and I'm looking to complete the unwind functionality by
disovering how to obtain the PC (not in a general register). However, after
arranging for a segfault
the unwind function is not being invoked at first and I get 2 backtrace
listings
with appropriate function name and line numbers, and only then does gdb
decide to call my unwind function and it does so with garbage data.
This is understandable to the extent gdb doesn't know the ocaml stack usage.
But if that's true, why would it proceed to generate 2 lines of backtrace
before
consulting my unwinder to gather the correct data?
My expectation is it would consult my unwinder immediately.
By the way, there is no frame pointing register used in the ocaml compiler
I'm using.
Any insights appreciated!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: GDB-JIT: why would my 'unwind' not be invoked on crash?
2025-11-11 21:26 ` Tom Tromey
@ 2025-11-12 2:00 ` K via Gdb
2025-11-12 15:50 ` Simon Marchi via Gdb
0 siblings, 1 reply; 5+ messages in thread
From: K via Gdb @ 2025-11-12 2:00 UTC (permalink / raw)
To: Tom Tromey; +Cc: K via Gdb
>
> Could you say more about what exactly you're doing?
>
> Like are you writing an unwinder in gdb? Or writing one in Python?
>
>
I'm implementing an unwinder via the GDB-JIT C API for JIT code where
generating custom ELF debug information is too onerous.
The first article I read on it, by the implementor Sanjoy D(?) mentioned
your name as originating the approach!
So I'm just providing the functions called for by the struct in the API -
unwind and get-frame-id (plus the function name/line number info
separately).
So gdb has no ELF info to look at (other than of the binary that is
generating the JIT code), so I was expecting gdb to immediately defer
to the jit-reader.so loaded into itself with the defined unwind function
which has a few printf statements so I know when it runs ...
and it isn't being called until 2 lines of backtrace have already been
emitted, and only then on garbage data because it has already gone awry
interpreting the stack contents/frame (with those first 2 lines above).
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: GDB-JIT: why would my 'unwind' not be invoked on crash?
2025-11-12 2:00 ` K via Gdb
@ 2025-11-12 15:50 ` Simon Marchi via Gdb
2025-11-14 6:33 ` K via Gdb
0 siblings, 1 reply; 5+ messages in thread
From: Simon Marchi via Gdb @ 2025-11-12 15:50 UTC (permalink / raw)
To: K, Tom Tromey; +Cc: K via Gdb
On 11/11/25 9:00 PM, K via Gdb wrote:
>>
>> Could you say more about what exactly you're doing?
>>
>> Like are you writing an unwinder in gdb? Or writing one in Python?
>>
>>
> I'm implementing an unwinder via the GDB-JIT C API for JIT code where
> generating custom ELF debug information is too onerous.
> The first article I read on it, by the implementor Sanjoy D(?) mentioned
> your name as originating the approach!
> So I'm just providing the functions called for by the struct in the API -
> unwind and get-frame-id (plus the function name/line number info
> separately).
>
> So gdb has no ELF info to look at (other than of the binary that is
> generating the JIT code), so I was expecting gdb to immediately defer
> to the jit-reader.so loaded into itself with the defined unwind function
> which has a few printf statements so I know when it runs ...
> and it isn't being called until 2 lines of backtrace have already been
> emitted, and only then on garbage data because it has already gone awry
> interpreting the stack contents/frame (with those first 2 lines above).
I don't have first hand experience in writing one of these, so I can't
help you directly. So as Tom said, I would probably end up debugging
GDB itself as well (which is an easy thing to say, given we're GDB
devs).
The functions involved in finding the appropriate unwinder are
frame_unwind_find_by_frame and frame_unwind_try_unwinder, here:
https://gitlab.com/gnutools/binutils-gdb/-/blob/30f6e34f1fad35f9e8a3230adf2b7268b2a5229f/gdb/frame-unwind.c#L187
The JIT support code prepends its unwinder here:
https://gitlab.com/gnutools/binutils-gdb/-/blob/30f6e34f1fad35f9e8a3230adf2b7268b2a5229f/gdb/jit.c#L1142
So when frame_unwind_try_unwinder runs with "set debug frame 1", trying
to find an unwinder for frame 0, I would expect to see a message like
`Trying unwinder "jit"`. And then your code should be called. This is
where I would start investigating.
Simon
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: GDB-JIT: why would my 'unwind' not be invoked on crash?
2025-11-12 15:50 ` Simon Marchi via Gdb
@ 2025-11-14 6:33 ` K via Gdb
0 siblings, 0 replies; 5+ messages in thread
From: K via Gdb @ 2025-11-14 6:33 UTC (permalink / raw)
Cc: K via Gdb
the debug shows gdb's own "aarch64 prologue" is matching first.
and it isn't wrong - I verified the first backtrace entry as correct.
I can't get into the gdb codebase though to find out why it unravels from
that point on.
I have the immediate source of my segfault and will run with that.
In the matter of aarch64's program counter: anyone know how to get this out
of the gdb-jit interface
given that the pc is not in a register?
On Wed, 12 Nov 2025 at 16:50, Simon Marchi <simark@simark.ca> wrote:
> On 11/11/25 9:00 PM, K via Gdb wrote:
> >>
> >> Could you say more about what exactly you're doing?
> >>
> >> Like are you writing an unwinder in gdb? Or writing one in Python?
> >>
> >>
> > I'm implementing an unwinder via the GDB-JIT C API for JIT code where
> > generating custom ELF debug information is too onerous.
> > The first article I read on it, by the implementor Sanjoy D(?) mentioned
> > your name as originating the approach!
> > So I'm just providing the functions called for by the struct in the API -
> > unwind and get-frame-id (plus the function name/line number info
> > separately).
> >
> > So gdb has no ELF info to look at (other than of the binary that is
> > generating the JIT code), so I was expecting gdb to immediately defer
> > to the jit-reader.so loaded into itself with the defined unwind function
> > which has a few printf statements so I know when it runs ...
> > and it isn't being called until 2 lines of backtrace have already been
> > emitted, and only then on garbage data because it has already gone awry
> > interpreting the stack contents/frame (with those first 2 lines above).
>
> I don't have first hand experience in writing one of these, so I can't
> help you directly. So as Tom said, I would probably end up debugging
> GDB itself as well (which is an easy thing to say, given we're GDB
> devs).
>
> The functions involved in finding the appropriate unwinder are
> frame_unwind_find_by_frame and frame_unwind_try_unwinder, here:
>
>
> https://gitlab.com/gnutools/binutils-gdb/-/blob/30f6e34f1fad35f9e8a3230adf2b7268b2a5229f/gdb/frame-unwind.c#L187
>
> The JIT support code prepends its unwinder here:
>
>
> https://gitlab.com/gnutools/binutils-gdb/-/blob/30f6e34f1fad35f9e8a3230adf2b7268b2a5229f/gdb/jit.c#L1142
>
> So when frame_unwind_try_unwinder runs with "set debug frame 1", trying
> to find an unwinder for frame 0, I would expect to see a message like
> `Trying unwinder "jit"`. And then your code should be called. This is
> where I would start investigating.
>
> Simon
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-11-14 4:35 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-11 21:43 GDB-JIT: why would my 'unwind' not be invoked on crash? K via Gdb
2025-11-11 21:26 ` Tom Tromey
2025-11-12 2:00 ` K via Gdb
2025-11-12 15:50 ` Simon Marchi via Gdb
2025-11-14 6:33 ` K via Gdb
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox