How to get the relative address of a field in a structure dump. [C]

For anyone reading this years later, maybe following a search engine result: Since gdb 8.1, its builtin ptype command has the /o flag for this.
It will print offset and size of MyType's members and also "holes" (padding), like:

(gdb) ptype /o MyType
/* offset    |  size */  type = class MyType {
/*  0        |     4 */    int foo;
/* XXX  4-byte hole  */
/*  8        |     8 */    void* ptr;
                           /* total size (bytes):  16 */
                         }


You can do it with gdb. As an example, I'll use this source:

struct A {
  int a;
  char b;
  short c;
};

int main() {
  struct A a;
}

Loading up the binary in gdb:

(gdb) print (int)&((struct A*)0)->a
$1 = 0
(gdb) print (int)&((struct A*)0)->b
$2 = 4
(gdb) print (int)&((struct A*)0)->c
$3 = 6

UPDATE:

If you need to do it for a large number of fields, then you may find it handy to use GDB's new python interface (you'll need a recent version of GDB to use it, I'm using 7.4). I've created offsets.py:

import gdb

class Offsets(gdb.Command):
    def __init__(self):
        super (Offsets, self).__init__ ('offsets-of', gdb.COMMAND_DATA)

    def invoke(self, arg, from_tty):
        argv = gdb.string_to_argv(arg)
        if len(argv) != 1:
            raise gdb.GdbError('offsets-of takes exactly 1 argument.')

        stype = gdb.lookup_type(argv[0])

        print argv[0], '{'
        for field in stype.fields():
            print '    %s => %d' % (field.name, field.bitpos//8)
        print '}'

Offsets()

Then you can add to your .gdbinit:

python
sys.path.insert(0, '/path/to/script/dir')
import offsets
end

Then using it in GDB, like:

(gdb) offsets-of "struct A"
struct A {
    a => 0
    b => 4
    c => 6
}

This script makes a few simplifying assumptions, like that you don't use bitfields, and it doesn't dig into nested structs, but those changes are3 fairly straightforward if you need them.

Tags:

C

Field

Dump