2012-03-20 48 views
6

我們正在研究在Linux下用arm-eabi-gcc編譯的C程序。如何獲取結構轉儲中字段的相對地址。 [C]

我們正在使用大型結構的轉儲,並且我們在確定在哪個地址應該讀取我們結構的各個字段(如其中的50個)時存在問題(存儲器對齊和填充不太可預測我)。

有什麼辦法可以獲得我們的編譯器生成的結構的內存映射。 gdb中的選項?或者任何幫助我們找到字段和地址之間的對應關係的工具?

+0

我可能在這裏丟失了一些明顯的東西,但是如果你有一個被聲明爲結構實例(或者結構體指針)的變量(比如'x'),那麼你應該只需要鍵入'在gdb中打印x'(或'print * x',如果是指針)來轉儲所有成員。 – 2012-03-20 15:34:04

+0

我不是想要獲得我想要轉儲的地址。我已經有了轉儲,需要所有成員的相對地址。 – Akhneyzar 2012-05-04 15:19:30

回答

23

您可以使用gdb。在gdb

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

int main() { 
    struct A a; 
} 

加載了二進制:作爲一個例子,我將使用這個源

(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:

如果你需要做的大量那麼你可能會發現使用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 
} 

這個腳本使得一些簡化的假設,就像你不使用位域一樣,它不會挖掘嵌套的結構,但如果你需要它們,那些變化是相當簡單的。

+0

我承諾,但我希望列出其中的50個所需字段。 – Akhneyzar 2012-03-20 14:44:18

+0

我做了一個更完整的版本,感謝靈感。 [Clicky](https://github.com/Craxic/PyGDBOffsets/blob/master/offsets.py) – AStupidNoob 2014-11-08 09:21:17

+0

你的'.gdbinit'看起來很奇怪。爲什麼不''source/path/to/script/dir/offsets.py' – zhangyoufu 2015-06-11 02:32:10

-1

在我看來,你可以寫一點像這樣的代碼爲必填字段

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

來計算這個編譯形勢字節偏移量。

這應該說明編譯器有任何對齊問題。

+0

但它缺少50個或更多字段的效率。 – Akhneyzar 2012-03-20 14:45:04

+0

這不會編譯:指針算術不允許您從X指針中減去指向S的指針。 – 2012-03-20 14:50:15

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從編譯的二進制獲得偏移量而不執行它。也許分配一個靜態變量的偏移值,並找到一些方法來獲得它的價值。

相關問題