2016-09-21 124 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之外的其他屬性,如果您想報告有關結構佈局的其他詳細信息,那麼這些屬性也可能是有用的。