为了方便起见,我想在GDB中定义一些辅助marcos,其中一个是offsetof()
宏。
我试过
define offsetof
if $argc == 2
(int)(&((($arg0 *)0)->$arg1))
end
end
它不起作用,因为:
struct node
等类型将被分为Struct
和node
,因此$arg0 = Struct
,$arg1 = node
。任何人都可以帮我一把吗?
答案 0 :(得分:9)
不是将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文档。
答案 1 :(得分: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
之外的其他属性,如果您想报告有关结构布局的其他详细信息,那么这些属性也可能会有用。