Как получить относительный адрес поля в дампе структуры.[С] - PullRequest
8 голосов
/ 20 марта 2012

Мы работаем над программой на C, скомпилированной с помощью arm-eabi-gcc под Linux.

Мы используем дамп большой структуры, и у нас возникают проблемы с определением адреса, по которому мы должны читать различные поля нашей структуры (около 50 из них), (выравнивание и заполнение памяти не такпредсказуемо для меня).

Есть ли способ получить отображение памяти структуры, созданной нашим компилятором.Опция в GDB?Или какой-нибудь инструмент, помогающий нам найти соответствие между полями и адресом в дампе?

Ответы [ 3 ]

31 голосов
/ 20 марта 2012

Вы можете сделать это с gdb. В качестве примера я буду использовать этот источник:

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

int main() {
  struct A a;
}

Загрузка двоичного файла в 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:

Если вам нужно сделать это для большого количества полей, то вам может пригодиться использование нового интерфейса Python в GDB (для его использования вам потребуется последняя версия GDB, я использую 7.4). Я создал 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()

Затем вы можете добавить в свой .gdbinit:

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

Затем используйте его в GDB, например:

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

Этот скрипт делает несколько упрощающих допущений, например, что вы не используете битовые поля, и он не копается во вложенных структурах, но эти изменения3 довольно просты, если они вам нужны.

2 голосов
/ 26 марта 2012

Вы можете сделать это из программы на C, используя стандартный макрос offsetof(), определенный в stddef.h. Однако я не уверен, что это то, что вам нужно, поскольку вы, возможно, не сможете его запустить (компиляция на хосте, скорее всего, вернет неправильные смещения).

#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;
}

Однако вы можете использовать некоторые хаки для получения смещения из скомпилированного двоичного файла без его выполнения. Возможно, назначьте статическую переменную значению смещения и найдите способ получить ее значение.

0 голосов
/ 20 марта 2012

Мне кажется, вы могли бы написать немного кода, подобного этому, для обязательных полей

struct MyStruct S;
int Offset_of_X=((long)&(S.X))-((long)&S);

для вычисления смещения в байтах в этой ситуации компиляции.

Это должно учитывать любыепроблемы с выравниванием у компилятора.

...