How to access the keys or values of Python GDB Value

Question:

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?

Asked By: Uhlo

||

Answers:

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']
Answered By: Speckinius Flecksis

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.

Answered By: Employed Russian

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 %dn", mystruct.member);
  for(uint8_t ix=0; ix<sizeof(mystruct.list); ix++) {
    printf("mystruct.list[%d]: %dn", 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 '00', list = "n2436(2"}
(gdb) python print(ms['member'])
0 '00'
(gdb) python print(ms['list'])
"n2436(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 '24'
mystruct.list[2]: 30 '36'
mystruct.list[3]: 40 '('
mystruct.list[4]: 50 '2'
Answered By: sdbbs
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.