6

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?

3 Answers 3

7

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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']

1 Comment

Thanks for this workaround! Sadly, it will not work for structs with strings or other structs inside. So this solution will not always work!
0

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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.