2016-09-21 121 views
1

为了方便,我想在GDB中定义一些辅助的marcos,其中之一就是offsetof()宏。如何在GDB中定义offsetof()宏

我试图

define offsetof 
    if $argc == 2 
     (int)(&((($arg0 *)0)->$arg1)) 
    end 
end 

它不工作: 1类不如struct node将分裂成Structnode,所以$arg0 = Struct$arg1 = node。 2.我不确定gdb的命令是否可以返回值。

任何人都可以帮我一把吗?

回答

5

而不是定义offsetof作为一个命令,我认为最好将其定义为一个函数。这样你可以在表达式中使用它;如果你只是想看到偏移量,你总是可以使用print

有两种方法可以将offsetof定义为函数。

如果调试C或C++,你可以简单地把它定义为一个宏:

(gdb) macro define offsetof(t, f) &((t *) 0)->f) 

所以给出:

struct x { 
    int a; 
    long b; 
}; 

在我的机器,我得到:

(gdb) p offsetof(struct x, a) 
$1 = (int *) 0x0 
(gdb) p offsetof(struct x, b) 
$2 = (long *) 0x8 

上述“C或C++”限制的原因是其他语言不通过gdb的内置预处理器运行它们的表达式。

如果你想让它在其他语言中工作,那么答案就是在Python中编写一个新的便利函数。这有点多,但请参阅gdb.Function的gdb文档。

0

如果您使用Python来定义offsetof,你可能会像这样开始:

import gdb 

class offsetof(gdb.Command): 

    def invoke(self, args, from_tty): 
     value, name = args.split() 
     struct = gdb.parse_and_eval(value) 
     fields = { field.name: field for field in struct.type.fields() } 
     gdb.write("{} offset: {} bits\n".format(name, fields[name].bitpos)) 

offsetof("offsetof", gdb.COMMAND_USER) 

如果您保存到一个文件,并确保该目录下保存它是在sys.path,你可以导入它。例如,如果你把它保存到你的主目录,你可能会做一些沿着这些路线:

(gdb) pi 
>>> import os 
>>> sys.path.insert(0, os.getenv('HOME')) 
>>> import offsetof 
>>> 
(gdb) 

如果你的GDB没有pi命令,你可以在前面加上python每个命令后一个>>>提示。

如果gdb输入offsetof而没有投诉,那么您应该能够调用offsetof作为gdb命令。正如所写,它期望两个参数(空格分隔),一个值和一个名字。如果该值是一个具有提供名称的字段的结构,则它将报告偏移量(不是字节,因为基础Python代码可以处理位域)。

这里的代码可以改进。除了它从它调用的代码继承的东西之外,它没有真正的错误处理,并且它不会处理指针。

This page描述了该示例中使用的一些底层代码;它提到的target方法可能会提供处理指针的开始(或者,您可以在传递的值中取消引用指针,即可指定*this而不是this作为第一个参数)。 Type.fields()上的部分提到除bitpos之外的其他属性,如果您想报告有关结构布局的其他详细信息,那么这些属性也可能是有用的。