Reputation: 435
I have a struct in GDB and want to run a script which examines this struct. In Python GDB you can easily access the struct via
(gdb) python mystruct = gdb.parse_and_eval("mystruct")
Now I got this variable called mystruct which is a GDB.Value object. And I can access all the members of the struct by simply using this object as a dictionary (likemystruct['member']
).
The problem is, that my script doesn't know which members a certain struct has. So I wanted to get the keys (or even the values) from this GDB.Value object. But neither mystruct.values()
nor mystruct.keys()
is working here.
Is there no possibility to access this information? I think it's highly unlikely that you can't access this information, but I didn't found it anywhere. A dir(mystruct)
showed me that there also is no keys or values function. I can see all the members by printing the mystruct, but isn't there a way to get the members in python?
Upvotes: 6
Views: 5550
Reputation: 5394
These days:
(gdb) python import sys; print(sys.version)
3.10.8 (main, Oct 15 2022, 19:00:40) [GCC 12.2.0 64 bit (AMD64)]
... it got a lot easier, properties are keys in dict - here is an example:
test_struct.c
:
#include <stdint.h>
#include <stdio.h>
struct mystruct_s {
uint8_t member;
uint8_t list[5];
};
typedef struct mystruct_s mystruct_t;
mystruct_t mystruct = {
.member = 0,
.list = { 10, 20, 30, 40, 50 },
};
int main(void) {
printf("mystruct.member %d\n", mystruct.member);
for(uint8_t ix=0; ix<sizeof(mystruct.list); ix++) {
printf("mystruct.list[%d]: %d\n", ix, mystruct.list[ix]);
}
}
Then compile and enter gdb:
gcc -g -o test_struct.exe test_struct.c
gdb --args ./test_struct.exe
... then in gdb:
(gdb) b main
Breakpoint 1 at 0x140001591: file test_struct.c, line 16.
(gdb) python ms = gdb.parse_and_eval("mystruct")
(gdb) python print(ms)
{member = 0 '\000', list = "\n\024\036(2"}
(gdb) python print(ms['member'])
0 '\000'
(gdb) python print(ms['list'])
"\n\024\036(2"
(gdb) python for ix in range(0,5): print("mystruct.list[{}]: {}".format(ix, ms['list'][ix]))
mystruct.list[0]: 10 '\n'
mystruct.list[1]: 20 '\024'
mystruct.list[2]: 30 '\036'
mystruct.list[3]: 40 '('
mystruct.list[4]: 50 '2'
Upvotes: 0
Reputation: 213646
From GDB documentation:
You can get the type of mystruct
like so:
tp = mystruct.type
and iterate over the fields via tp.fields()
No evil workarounds required ;-)
Update: GDB 7.4 has just been released. From the announcement:
Type objects for struct and union types now allow access to the fields using standard Python dictionary (mapping) methods.
Upvotes: 7
Reputation: 624
Evil workaround:
python print eval("dict(" + str(mystruct)[1:-2] + ")")
I don't know if this is generalisable. As a demo, I wrote a minimal example test.cpp
#include <iostream>
struct mystruct
{
int i;
double x;
} mystruct_1;
int main ()
{
mystruct_1.i = 2;
mystruct_1.x = 1.242;
std::cout << "Blarz";
std::cout << std::endl;
}
Now I run g++ -g test.cpp -o test
as usual and fire up gdb test
. Here is a example session transcript:
(gdb) break main
Breakpoint 1 at 0x400898: file test.cpp, line 11.
(gdb) run
Starting program: ...
Breakpoint 1, main () at test.cpp:11
11 mystruct_1.i = 2;
(gdb) step
12 mystruct_1.x = 1.242;
(gdb) step
13 std::cout << "Blarz";
(gdb) python mystruct = gdb.parse_and_eval("mystruct_1")
(gdb) python print mystruct
{i = 2, x = 1.242}
(gdb) python print eval("dict(" + str(mystruct)[1:-2] + ")")
{'i': 2, 'x': 1.24}
(gdb) python print eval("dict(" + str(mystruct)[1:-2] + ")").keys()
['i', 'x']
Upvotes: 1