Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

field

dump

We're working on a C program compiled with arm-eabi-gcc under Linux.

We're using a dump of a large structure and we're having problems determining at which adress we should read various fields of our structure (like 50 of them), (memory alignement and padding aren't so predictable to me).

Is there any way to get the memory mapping of the structure produced by a our compiler. An option in gdb? Or any tool helping us find the correspondance between fields and adress in the dump?

like image 490
Akhneyzar Avatar asked Mar 20 '12 14:03

Akhneyzar


3 Answers

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 */
                         }

like image 55
Daniel Avatar answered Nov 04 '22 04:11

Daniel


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.

like image 30
FatalError Avatar answered Nov 04 '22 02:11

FatalError


You can do it from a C program using the standard offsetof() macro, defined in stddef.h. However I'm not sure this is what you want, since you may be unable to run it (compiling it on the host will likely return wrong offsets).

#include <stdio.h>
#include <stddef.h>

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

int main() {
    printf("Offset of b in A is %zu\n", offsetof(struct A, b));
    return 0;
}

However, you may be able to employ some hacks to get the offset from a compiled binary without executing it. Maybe assign a static variable the offset value, and find some way of getting its value.

like image 25
Ambroz Bizjak Avatar answered Nov 04 '22 04:11

Ambroz Bizjak