How to obtain the function boundaries from the Python API

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

How to obtain the function boundaries from the Python API

Andrea Cardaci
Hi,

This is a long-standing problem for me, every time I think I've fixed it,
some use case comes out and breaks my code again... so I'm asking here with
the hope to obtain a definitive solution.

In short, I'd like to obtain the (current) function boundaries using the
Python API.

Here's a sample C++ program:

    #include <iostream>
    #include <initializer_list>

    void foo(std::initializer_list<int> list) {
        asm("int3");
        for (auto x : list) {}
    }

    int main() {
        foo({});
    }

Compile with:

    g++ -ggdb3 function-boundaries.cpp -o function-boundaries

Then debug with:

    gdb function-boundaries -ex run -ex disassemble

In my case disassemble shows that the main function first and last
instruction are at 0x0000555555555145 and 0x00005555555551a3 respectively,
I'd like to obtain the same values using the Python API. This is what I
tried...

This gives a subset of the whole function starting from the PC:

    python
    block = gdb.block_for_pc(gdb.selected_frame().pc())
    print(hex(block.start), hex(block.end))
    end

This yields the same result:

    python
    block = gdb.selected_frame().block()
    print(hex(block.start), hex(block.end))
    end

This correctly gives the function address but then I don't know how to
obtain the end address:

    python print(gdb.selected_frame().function().value())

This gives a way bigger block:

    python
    block = gdb.selected_frame().function().symtab.static_block()
    print(hex(block.start), hex(block.end))
    end

The only thing that *seems* to work is the following:

    frame = gdb.selected_frame()
    block = frame.block()
    if frame.function():
        while block and (not block.function or
                         block.function.name != frame.function().name):
            block = block.superblock
        block = block or frame.block()

(Maybe the while is not needed and the worst case is to try the superblock
just once?)

But honestly I feel bad about this... is there a canonical solution to this
problem?


Thank you,
Andrea