Uhlo
Uhlo

Reputation: 435

How to access the keys or values of Python GDB Value

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

Answers (3)

sdbbs
sdbbs

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

Employed Russian
Employed Russian

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

Speckinius Flecksis
Speckinius Flecksis

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

Related Questions