It would be nice to automate full access to gdb internals via MI. The idea would be, expose all MI commands in a new module, gdb.mi. (Or perhaps versioned: gdb.mi2, gdb.mi3, ...) The wrapper would turn python-style arguments into what the MI commands expect. We'd make a new ui_out object that knows how to create Python objects. The wrapper function would return the python object created when the MI command is invoked. For documentation we could simply refer to the MI docs, with some explanation of how the translations are done.
Created attachment 5914 [details] a quick and ugly hack on this... here is a quick ugly patch for this which i am abandoning, though I got it partially working, the mi_execute() python function does some truly awful things, such that I think that specific approach is a dead end.. the py-mi-out needs error checking/a careful review of reference counting. and it was only tested with -break-insert/-break-list and -trace-status. I just think its more worth my time to do real python API's which have nicer output, than the amount of effort that this will require to get this functioning correctly and into a commitable form.
This patch looks pretty good as a start. There are some minor nits (formatting, some missing error checks) but nothing too major. It would be nice to expose the MI commands more naturally to Python, but I that isn't really a requirement. I tend to agree that writing Python APIs is probably a better approach. Although I filed this bug, I'm not convinced that exposing MI in this way is worth doing.
So I guess i changed my mind about working on this, with my main motivation being that it might make an ok alternative wire format to mi for an interface, e.g. using python on the client side with eval, dodging an mi parser all-together... something like this, with print repr on the gdb side, and eval on the client side... seems worth experimenting with anyways. (gdb) py print eval(repr(gdb.mi_execute('break-insert', 'main'))) {'bkpt': {'disp': 'keep', 'file': 'test.c', 'number': 3, 'func': 'main', 'line': 34, 'original-location': 'main', 'addr': '0x0000000000400509', 'enabled': 'y', 'times': 0, 'fullname': '/home/ratmice/tests/test.c', 'type': 'breakpoint'}} i've pretty much redone the python mi_execute command, to be less of a hack and managed to coax it into outputting dictionaries, or lists instead of lists of lists or tuples, i think its nicer... (gdb) py stuff.append(gdb.mi_execute("break-insert", "main")) (gdb) py x = stuff[-1]['bkpt']['number'] (gdb) py gdb.mi_execute("break-after", (x, 76)) (gdb) py print x 3 (gdb) info b 3 Num Type Disp Enb Address What 3 breakpoint keep y 0x0000000000400509 in main at test.c:34 ignore next 76 hits
Would you mind if I (eventually) extracted the ui-out portions of this separately? I think I have a use for that code in normal-stop event emission.
No I wouldn't mind at all, although I would prefer to base it on my 2nd version of the patch, I seem to have misplaced it, I'll redo the ui-out portions of that patch and post it here prior to '(eventually)'
Created attachment 6151 [details] 2nd implementation of ui-out for python here's the ui-out portion from my latest attempt at this separated from the mi_execute stuff, I'm not entirely pleased with the python objects this creates, as it does not always return consistent types. break-list is a nice easy way to hit all of the edge cases where ui-out does this. # first it returns None... for no breakpoints gdb.mi_execute("break-list", None)['body'] == None gdb.mi_execute("break-insert", ("main")) # then it returns a dictionary gdb.mi_execute("break-list", None)['body']['bkpt']['number'] gdb.mi_execute("break-insert", ("main")) # now its been promoted to a list as there are 2 breakpoints. gdb.mi_execute("break-list", None)['body']['bkpt'][-1]['number'] thus i am hesitant to think it returns objects of acceptable quality, unless used in a fashion which doesn't hit these edge cases. It does seem possible that we might be able to rid ourselves of these by expanding the existing ui_out_type, enum ui_out_type { ui_out_type_tuple, ui_out_type_list }; the necessary additions would be something along the lines of: ui_out_type_tuple_with_duplicate_keys ui_out_type_deprecated_tuple_list ui_out_type_deprecated_tuple_list_with_duplicate_keys (duplicate keys are the cause of object->array promotion, and empty lists/tuples are the cause of None.) that would also mean updating all callers, which seems like quite the endeavor. Other than that the code still needs lots of error handling, but alas I don't really want to finish that if the type schizophrenia means its a dead end. all of this does make me think that a 'py-mi-version' independent of mi-version for the return values might be warranted.
Created attachment 6152 [details] an implementation of mi_execute for python... heres a different version of mi_execute, which gets rid of ^done being printed on stdout, and does different argument handling.
Created attachment 6153 [details] a gdb script for testing... not an actual testcase yet.
I have a patch for this. I think maybe the break-info bugs were fixed as part of the MI upgrades? Anyway the output seems generally sane to me now and if we do find other bad spots, we ought to fix those.
Spiffy, I will keep an eye out for it on the lists/here, and look forward to giving it a try! (Unless i have missed it already, in which case I don't seem to be able to find it)
I haven't sent it yet, probably will next week.
https://sourceware.org/pipermail/gdb-patches/2023-April/198606.html
The master branch has been updated by Tom Tromey <tromey@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c97d123d6701fbf462e96db001cea07ed32e4efa commit c97d123d6701fbf462e96db001cea07ed32e4efa Author: Tom Tromey <tromey@adacore.com> Date: Thu Mar 16 10:57:32 2023 -0600 Implement gdb.execute_mi This adds a new Python function, gdb.execute_mi, that can be used to invoke an MI command but get the output as a Python object, rather than a string. This is done by implementing a new ui_out subclass that builds a Python object. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=11688 Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Fixed.