Bug 13326 - Need support for C++ method call for a gdb.Value object from within python
Summary: Need support for C++ method call for a gdb.Value object from within python
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: python (show other bugs)
Version: 7.3
: P2 normal
Target Milestone: 15.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-10-20 05:13 UTC by Xun Lai
Modified: 2024-06-03 15:26 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Xun Lai 2011-10-20 05:13:45 UTC
The python scripting support is great.

There is support for function call if a gdb.Value object is of type TYPE_CODE_FUNC.

There is no support for method call yet if a gdb.Value object is of type TYPE_CODE_METHOD.

In order to support the pretty-pritters for some classes, sometimes we need to call an method instead of just accessing some member fields.

Thanks,
Xun
Comment 1 vuvova 2017-08-03 09:59:48 UTC
Same for TYPE_CODE_INTERNAL_FUNCTION:

(gdb) pi a=gdb.parse_and_eval('$_streq')
(gdb) pi print a.type.code == gdb.TYPE_CODE_INTERNAL_FUNCTION
True
(gdb) pi a("1","2")
Python Exception <type 'exceptions.RuntimeError'> Value is not callable (not TYPE_CODE_FUNC).:
Comment 2 Phil Muldoon 2017-08-07 10:35:11 UTC
I looked at the code and, indeed, class method invocation is barred. I suspect the reason for this is two-fold. Currently, in GDB we evaluate all the hairy C++ stuff in the evaluation parser. The Python inferior function call stuff just calls "call_function_by_hand". This causes, firstly, the separation from the "this" reference which is passed as a parameter to the function. If you remove the restriction in the code, GDB will complain about an incorrect number of arguments because the hidden "this" argument is missing. Secondly, all of the extra "shaping" for the function call is missing like overload resolution. 

So feature missing confirmed. I'm not sure when it will be worked on as it is a non-trivial issue. Perhaps when the C++ification progresses to the evaluation parser it might be possible without duplicating large amounts of code.

There is a workaround available. You can use gdb.parse_and_eval to get the value by using it to call the function in question. This uses the evaluation parser and correctly sets up for the C++ function call. So something like:

python f = gdb.parse_and_eval("someObject.someFunction()") 

This will call that function and return the value back to GDB as a Python value.
Comment 3 Malcolm Parsons 2021-01-21 19:27:40 UTC
Use from a python pretty-printer is a bit convoluted, but it works:

def to_string(self):
    gdb.set_convenience_variable('_tmp', self.val.reference_value())
    return gdb.parse_and_eval('$_tmp.str()')
Comment 4 Sourceware Commits 2024-02-08 19:10:27 UTC
The master branch has been updated by Hannes Domani <ssbssa@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2e08907d0672711617f71ef4604df190106b992e

commit 2e08907d0672711617f71ef4604df190106b992e
Author: Hannes Domani <ssbssa@yahoo.de>
Date:   Thu Feb 8 20:09:25 2024 +0100

    Allow calling of C++ methods from python
    
    Currently it's not possible to call C++ methods from python.
    Using this example:
    ```
    class B
    {
      static int static_func ();
      int arg0_func ();
      int arg1_func (int arg1);
      int arg2_func (int arg1, int arg2);
    };
    
    B *b_obj = new B;
    ```
    
    Trying to call B::static_func gives this error:
    ```
    (gdb) py b_obj = gdb.parse_and_eval('b_obj')
    (gdb) py print(b_obj['static_func']())
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
    Error while executing Python code.
    ```
    
    TYPE_CODE_METHOD was simply missing as a possible type in
    valpy_call, now the same is possible:
    ```
    (gdb) py b_obj = gdb.parse_and_eval('b_obj')
    (gdb) py print(b_obj['static_func']())
    1111
    ```
    
    Note that it's necessary to explicitely add the this pointer
    as the first argument in a call of non-static methods:
    ```
    (gdb) py print(b_obj['arg0_func']())
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    gdb.error: Too few arguments in function call.
    Error while executing Python code.
    (gdb) py print(b_obj['arg0_func'](b_obj))
    198
    ```
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13326
    Approved-By: Tom Tromey <tom@tromey.com>
Comment 5 Hannes Domani 2024-02-08 19:13:16 UTC
Fixed.
Comment 6 Sourceware Commits 2024-06-03 15:19:08 UTC
The master branch has been updated by Hannes Domani <ssbssa@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f74da7b8b3d6f14ba9ad21b380f743e4bdc4e952

commit f74da7b8b3d6f14ba9ad21b380f743e4bdc4e952
Author: Hannes Domani <ssbssa@yahoo.de>
Date:   Mon Jun 3 17:18:30 2024 +0200

    Allow calling of convenience functions with python
    
    As mentioned in PR13326, currently when you try to call a
    convenience function with python, you get this error:
    
    (gdb) py print(gdb.convenience_variable("_isvoid")(3))
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    RuntimeError: Value is not callable (not TYPE_CODE_FUNC or TYPE_CODE_METHOD).
    Error while executing Python code.
    
    So this extends valpy_call to handle TYPE_CODE_INTERNAL_FUNCTION as
    well, making this possible:
    
    (gdb) py print(gdb.convenience_variable("_isvoid")(3))
    0
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13326
    Approved-By: Tom Tromey <tom@tromey.com>
Comment 7 Hannes Domani 2024-06-03 15:26:30 UTC
(In reply to vuvova from comment #1)
> Same for TYPE_CODE_INTERNAL_FUNCTION:
> 
> (gdb) pi a=gdb.parse_and_eval('$_streq')
> (gdb) pi print a.type.code == gdb.TYPE_CODE_INTERNAL_FUNCTION
> True
> (gdb) pi a("1","2")
> Python Exception <type 'exceptions.RuntimeError'> Value is not callable (not
> TYPE_CODE_FUNC).:

Now this is fixed as well.