如何获取结构转储中字段的相对地址。 [C]

问题描述 投票:8回答:3

我们正在开发一个在Linux下用arm-eabi-gcc编译的C程序。

我们正在使用一个大型结构的转储,我们在确定我们应该在哪个地址读取我们结构的各个字段(比如50个)时遇到问题,(内存对齐和填充对我来说不是那么可预测)。

有没有办法获得我们的编译器生成的结构的内存映射。 gdb中的一个选项?或者帮助我们找到转储中字段和地址之间的对应关系的任何工具?

c field dump
3个回答
30
投票

你可以用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

更新:

如果您需要为大量字段执行此操作,那么您可能会发现使用GDB的新python接口很方便(您需要最新版本的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
}

这个脚本做了一些简化的假设,比如你没有使用位域,并且它没有深入研究嵌套结构,但是如果你需要它们,这些变化相当简单。


2
投票

你可以使用offsetof()中定义的标准stddef.h宏从C程序中完成。但是我不确定这是你想要的,因为你可能无法运行它(在主机上编译它可能会返回错误的偏移量)。

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

但是,您可以使用一些hack来从已编译的二进制文件中获取偏移量而不执行它。也许为静态变量赋予偏移值,并找到获取其值的某种方法。


-1
投票

在我看来,您可以为必填字段编写一些这样的代码

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

计算此编译情况下的字节偏移量。

这应该解释编译器具有的任何对齐问题。

© www.soinside.com 2019 - 2024. All rights reserved.