Thread Specific Architectures And Python Unwinder API

Andrew Burgess
Wed Oct 11 08:47:08 GMT 2023

Hi Luis,

While working on something else I was looking at the Python Unwinder API
code, and I suspect that the thread-specific architectures support might
(currently) break the Python Unwinder support.

If it is, then I think the fix is pretty simple, but before I posted it,
I wondered if you could confirm that things are indeed, currently

Attached at the end of this email is a Python unwinder.  You'll need to
supply your own test program that makes use of sve/sme, and thus uses
thread-specific architectures.

What you'll need to do is:

  $ gdb -q test_file_that_uses_sve_sme
  Reading symbols from .... etc ...
  (gdb) source ./
  (gdb) break function_where_a_thread_specific_arch_will_be_in_use
  Breakpoint 1 at ... etc ...
  (gdb) run
  Starting program: ... etc ...

Now at this point, when you stop, you should see at least one instance
of the banner:
  * Have executed the test unwinder *

being printed, probably more.  As you step though the function you
should see more instances of the banner being printed.

To reveal the bug then it is important that when GDB stops in
function_where_a_thread_specific_arch_will_be_in_use, the per-thread
gdbarch that it creates _must_ be different from the inferior wide,
top-level gdbarch.

If you don't see the banner then my suspicion is correct, and the Python
Unwinder API was broken when the thread-specific architecture support
was added.

The problem (I think) is that the Python unwinder is registered on each
gdbarch as a result of the gdb::observers::architecture_changed.notify()
call in set_target_gdbarch (though Simon has recently moved, or is about
to move, this code, but not in a way that will fix this problem).  Thus,
the Python unwinder is only registered on the top-level (inferior wide)
gdbarch, not on each of the different per-thread architectures.

I have a patch here that removes the 'architecture_changed' observer,
and replaces it with a 'new_architecture' observer, which I propose to
move up into gdbarch_find_by_info.



from gdb.unwinder import Unwinder, FrameId

class test_unwinder(Unwinder):
    def __init__(self):

    def __call__(self,pending_frame):
        print("* Have executed the test unwinder *")
        return None

gdb.unwinder.register_unwinder(None, test_unwinder(), replace=True)

More information about the Gdb mailing list